home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / term43-source.lha / Extras / Source / term-Source.lha / termAux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-16  |  82.4 KB  |  4,598 lines

  1. /*
  2. **    termAux.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* This variable stores the current state of the
  13.      * dialing menu items.
  14.      */
  15.  
  16. STATIC BYTE DialItemsAvailable = TRUE;
  17.  
  18.     /* Current timer state. */
  19.  
  20. STATIC BYTE TimerRunning = FALSE;
  21.  
  22. STATIC VOID
  23. StuffChar(VOID)
  24. {
  25.     __emit(0x16C0);    /* MOVE D0,(A3)+ */
  26. }
  27.  
  28.     /* SPrintf(STRPTR Buffer,STRPTR FormatString,...):
  29.      *
  30.      *    Just like sprintf(), but using the ROM routines.
  31.      */
  32.  
  33. VOID __stdargs
  34. SPrintf(STRPTR Buffer,STRPTR FormatString,...)
  35. {
  36.     va_list VarArgs;
  37.  
  38.     va_start(VarArgs,FormatString);
  39.     RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Buffer);
  40.     va_end(VarArgs);
  41. }
  42.  
  43.     /* VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs):
  44.      *
  45.      *    Just like vsprintf(), but using the ROM routines.
  46.      */
  47.  
  48. VOID __regargs
  49. VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs)
  50. {
  51.     RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Buffer);
  52. }
  53.  
  54.     /* Atol(STRPTR Buffer):
  55.      *
  56.      *    Convert ASCII representation to long word.
  57.      */
  58.  
  59. LONG __regargs
  60. Atol(STRPTR Buffer)
  61. {
  62.     LONG Result;
  63.  
  64.     StrToLong(Buffer,&Result);
  65.  
  66.     return(Result);
  67. }
  68.  
  69.     /* StripSpaces(STRPTR String):
  70.      *
  71.      *    Strip leading and trailing spaces from a string.
  72.      */
  73.  
  74. VOID __regargs
  75. StripSpaces(STRPTR String)
  76. {
  77.     if(String)
  78.     {
  79.         STRPTR    To = String;
  80.         WORD    Len;
  81.  
  82.         while(*String == ' ')
  83.             String++;
  84.  
  85.         if(Len = strlen(String))
  86.         {
  87.             while(Len > 0 && String[Len - 1] == ' ')
  88.                 Len--;
  89.  
  90.             while(Len--)
  91.                 *To++ = *String++;
  92.         }
  93.  
  94.         *To = 0;
  95.     }
  96. }
  97.  
  98.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  99.      *
  100.      *    Drop the window info into the right place.
  101.      */
  102.  
  103. VOID __regargs
  104. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  105. {
  106.     WORD i;
  107.  
  108.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  109.     {
  110.         if(WindowInfoTable[i] . ID == NewInfo -> ID)
  111.         {
  112.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  113.  
  114.             break;
  115.         }
  116.     }
  117. }
  118.  
  119.     /* PutWindowInfo():
  120.      *
  121.      *    Store window size and position relative to
  122.      *    the main window.
  123.      */
  124.  
  125. VOID __regargs
  126. PutWindowInfo(UBYTE ID,LONG Left,LONG Top,LONG Width,LONG Height)
  127. {
  128.     struct WindowInfo    *Info;
  129.     WORD             i;
  130.     LONG             WindowLeft,
  131.                  WindowTop,
  132.                  WindowWidth,
  133.                  WindowHeight;
  134.     ULONG             IntuiLock;
  135.  
  136.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  137.     {
  138.         if(WindowInfoTable[i] . ID == ID)
  139.         {
  140.             Info = &WindowInfoTable[i];
  141.  
  142.             break;
  143.         }
  144.     }
  145.  
  146.     IntuiLock = LockIBase(NULL);
  147.  
  148.     WindowLeft    = Window -> LeftEdge;
  149.     WindowTop    = Window -> TopEdge;
  150.     WindowWidth    = Window -> Width;
  151.     WindowHeight    = Window -> Height;
  152.  
  153.     UnlockIBase(IntuiLock);
  154.  
  155.     Forbid();
  156.  
  157.     Info -> WindowFlags = NULL;
  158.  
  159.     if(WindowWidth == Width && WindowLeft == Left)
  160.         Info -> WindowFlags |= WC_EXPANDWIDTH;
  161.     else
  162.     {
  163.         if(Left == WindowLeft + WindowWidth)
  164.             Info -> WindowFlags |= WC_ALIGNSIDE;
  165.  
  166.         if(WindowLeft == Left)
  167.             Info -> WindowFlags |= WC_ALIGNLEFT;
  168.  
  169.         if(WindowLeft + WindowWidth == Left + Width)
  170.             Info -> WindowFlags |= WC_ALIGNRIGHT;
  171.     }
  172.  
  173.     if(WindowHeight == Height && WindowTop == Top)
  174.         Info -> WindowFlags |= WC_EXPANDHEIGHT;
  175.     else
  176.     {
  177.         if(Top == WindowTop + WindowHeight)
  178.             Info -> WindowFlags |= WC_ALIGNBELOW;
  179.  
  180.         if(WindowTop == Top)
  181.             Info -> WindowFlags |= WC_ALIGNTOP;
  182.  
  183.         if(WindowTop + WindowHeight == Top + Height)
  184.             Info -> WindowFlags |= WC_ALIGNBOTTOM;
  185.     }
  186.  
  187.     Info -> Left    = Left;
  188.     Info -> Top    = Top;
  189.     Info -> Width    = Width;
  190.     Info -> Height    = Height;
  191.  
  192.     Permit();
  193. }
  194.  
  195.     /* GetWindowInfo():
  196.      *
  197.      *    Set the window size and position in relation to
  198.      *    the main window.
  199.      */
  200.  
  201. VOID __regargs
  202. GetWindowInfo(UBYTE ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  203. {
  204.     struct WindowInfo    *Info;
  205.     WORD             i;
  206.     LONG             WindowLeft,
  207.                  WindowTop,
  208.                  WindowWidth,
  209.                  WindowHeight;
  210.     ULONG             IntuiLock;
  211.  
  212.     if(Window)
  213.     {
  214.         if(DefWidth && DefWidth < Window -> Width / 2)
  215.             DefWidth = Window -> Width / 2;
  216.  
  217.         if(DefHeight && DefHeight < Window -> Height / 2)
  218.             DefHeight = Window -> Height / 2;
  219.     }
  220.  
  221.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  222.     {
  223.         if(WindowInfoTable[i] . ID == ID)
  224.         {
  225.             Info = &WindowInfoTable[i];
  226.  
  227.             break;
  228.         }
  229.     }
  230.  
  231.     if(Info && ID == WINDOW_MAIN)
  232.     {
  233.         *Left    = Info -> Left;
  234.         *Top    = Info -> Top;
  235.  
  236.         return;
  237.     }
  238.  
  239.     if(Window)
  240.     {
  241.         IntuiLock = LockIBase(NULL);
  242.  
  243.         WindowLeft    = Window -> LeftEdge;
  244.         WindowTop    = Window -> TopEdge + Window -> BorderTop;
  245.         WindowWidth    = Window -> Width;
  246.         WindowHeight    = Window -> Height - Window -> BorderTop;
  247.  
  248.         UnlockIBase(IntuiLock);
  249.     }
  250.  
  251.     Forbid();
  252.  
  253.     if(*Width)
  254.     {
  255.         if(Info -> Width)
  256.             *Left = Info -> Left;
  257.         else
  258.             *Left = WindowLeft + (WindowWidth - *Width) / 2;
  259.     }
  260.     else
  261.     {
  262.         if(DefWidth && !Info -> Width)
  263.         {
  264.             *Width    = DefWidth;
  265.             *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  266.         }
  267.         else
  268.         {
  269.             if(Info -> Width)
  270.             {
  271.                 *Width    = Info -> Width;
  272.                 *Left    = Info -> Left;
  273.             }
  274.             else
  275.             {
  276. /*                *Width    = WindowWidth / 2;*/
  277. /*                *Left    = WindowLeft + WindowWidth / 4;*/
  278.  
  279.                 *Width    = WindowWidth;
  280.                 *Left    = WindowLeft;
  281.             }
  282.         }
  283.     }
  284.  
  285.     if(*Height)
  286.     {
  287.         if(Info -> Height)
  288.             *Top = Info -> Top;
  289.         else
  290.             *Top = WindowTop + (WindowHeight - *Height) / 2;
  291.     }
  292.     else
  293.     {
  294.         if(DefHeight && !Info -> Height)
  295.         {
  296.             *Height    = DefHeight;
  297.             *Top    = WindowTop + (WindowHeight - *Height) / 2;
  298.         }
  299.         else
  300.         {
  301.             if(Info -> Height)
  302.             {
  303.                 *Height    = Info -> Height;
  304.                 *Top    = Info -> Top;
  305.             }
  306.             else
  307.             {
  308. /*                *Height    = WindowHeight / 2;*/
  309. /*                *Top    = WindowTop + WindowHeight / 4;*/
  310.  
  311.                 *Height    = WindowHeight;
  312.                 *Top    = WindowTop;
  313.             }
  314.         }
  315.     }
  316.  
  317.     if(Info -> WindowFlags & WC_ALIGNSIDE)
  318.         *Left = WindowLeft + WindowWidth;
  319.  
  320.     if(Info -> WindowFlags & WC_ALIGNBELOW)
  321.         *Top = WindowTop + WindowHeight;
  322.  
  323.     if(Info -> WindowFlags & WC_ALIGNLEFT)
  324.         *Left = WindowLeft;
  325.  
  326.     if(Info -> WindowFlags & WC_ALIGNTOP)
  327.         *Top = WindowTop;
  328.  
  329.     if(Info -> WindowFlags & WC_ALIGNRIGHT)
  330.         *Left = WindowLeft + WindowWidth - *Width;
  331.  
  332.     if(Info -> WindowFlags & WC_ALIGNBOTTOM)
  333.         *Top = WindowTop + WindowHeight - *Height;
  334.  
  335.     if(Info -> WindowFlags & WC_EXPANDWIDTH)
  336.         *Width = WindowWidth;
  337.  
  338.     if(Info -> WindowFlags & WC_EXPANDHEIGHT)
  339.         *Height = WindowHeight;
  340.  
  341.     Permit();
  342. }
  343.  
  344.     /* GetBitMapDepth(struct BitMap *BitMap):
  345.      *
  346.      *    Return the depth of a BitMap.
  347.      */
  348.  
  349. LONG __regargs
  350. GetBitMapDepth(struct BitMap *BitMap)
  351. {
  352.     if(Kick30)
  353.         return((LONG)GetBitMapAttr(BitMap,BMA_DEPTH));
  354.     else
  355.         return(BitMap -> Depth);
  356. }
  357.  
  358.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  359.      *
  360.      *    Get screen DPI resolution values.
  361.      */
  362.  
  363. VOID __regargs
  364. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  365. {
  366.     struct DisplayInfo DisplayInfo;
  367.  
  368.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  369.     {
  370.         *X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
  371.         *Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
  372.     }
  373.     else
  374.         *X_DPI = *Y_DPI = 72;
  375. }
  376.  
  377.     /* AddProtection(STRPTR FileName,ULONG Mask):
  378.      *
  379.      *    Set bits in the protection mask of a file.
  380.      */
  381.  
  382. VOID __regargs
  383. AddProtection(STRPTR Name,ULONG Mask)
  384. {
  385.     struct FileInfoBlock *FileInfo;
  386.  
  387.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  388.     {
  389.         BPTR FileLock;
  390.  
  391.         if(FileLock = Lock(Name,ACCESS_READ))
  392.         {
  393.             if(Examine(FileLock,FileInfo))
  394.             {
  395.                 UnLock(FileLock);
  396.  
  397.                 SetProtection(Name,FileInfo -> fib_Protection | Mask);
  398.             }
  399.             else
  400.                 UnLock(FileLock);
  401.         }
  402.  
  403.         FreeDosObject(DOS_FIB,FileInfo);
  404.     }
  405. }
  406.  
  407.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  408.      *
  409.      *    Get the name of a public screen.
  410.      */
  411.  
  412. BYTE __regargs
  413. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  414. {
  415.     struct List        *PubScreenList;
  416.     struct PubScreenNode    *ScreenNode;
  417.  
  418.     PubScreenList = LockPubScreenList();
  419.  
  420.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  421.     {
  422.         if(ScreenNode -> psn_Screen == Screen)
  423.         {
  424.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  425.  
  426.             UnlockPubScreenList();
  427.  
  428.             return(TRUE);
  429.         }
  430.     }
  431.  
  432.     UnlockPubScreenList();
  433.  
  434.     return(FALSE);
  435. }
  436.  
  437.     /* InitSinglePort(struct MsgPort *Port):
  438.      *
  439.      *    Initialize a plain MsgPort (as created on the stack) for
  440.      *    usage. Don't try this at home, kids!
  441.      */
  442.  
  443. VOID __regargs
  444. InitSinglePort(struct MsgPort *Port)
  445. {
  446.     memset(Port,0,sizeof(struct MsgPort));
  447.  
  448.     Port -> mp_Flags    = PA_SIGNAL;
  449.     Port -> mp_SigBit    = SIGB_SINGLE;
  450.     Port -> mp_SigTask    = SysBase -> ThisTask;
  451.  
  452.     NewList(&Port -> mp_MsgList);
  453. }
  454.  
  455.     /* GoodStream(BPTR Stream):
  456.      *
  457.      *    Check to see whether the current input file
  458.      *    is an interactive stream.
  459.      */
  460.  
  461. BYTE __regargs
  462. GoodStream(BPTR Stream)
  463. {
  464.     if(!Stream)
  465.     {
  466.         struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  467.  
  468.         Stream = ThisProcess -> pr_CIS;
  469.     }
  470.  
  471.     if(Stream)
  472.     {
  473.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  474.  
  475.         if(Handle -> fh_Type)
  476.         {
  477.             if(IsInteractive(Stream))
  478.                 return(TRUE);
  479.         }
  480.     }
  481.  
  482.     return(FALSE);
  483. }
  484.  
  485.     /* GetProgramIcon():
  486.      *
  487.      *    Try to find the icon of the program.
  488.      */
  489.  
  490. struct DiskObject *
  491. GetProgramIcon()
  492. {
  493.     struct DiskObject *Icon = NULL;
  494.  
  495.         /* Run from Workbench? */
  496.  
  497.     if(WBenchMsg)
  498.     {
  499.             /* Sanity check. */
  500.  
  501.         if(WBenchMsg -> sm_ArgList)
  502.         {
  503.                 /* Yet another sanity check. */
  504.  
  505.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  506.             {
  507.                     /* Try to find the icon in the current directory. */
  508.  
  509.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  510.                 {
  511.                     if(Icon -> do_Type != WBTOOL)
  512.                     {
  513.                         FreeDiskObject(Icon);
  514.  
  515.                         Icon = NULL;
  516.                     }
  517.                 }
  518.  
  519.                 if(!Icon)
  520.                 {
  521.                     BPTR NewLock;
  522.  
  523.                         /* Move to the directory the
  524.                          * program was run from.
  525.                          */
  526.  
  527.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  528.                     {
  529.                         BPTR OldLock;
  530.  
  531.                         OldLock = CurrentDir(NewLock);
  532.  
  533.                             /* Try to fetch the icon, use the
  534.                              * default name if necessary.
  535.                              */
  536.  
  537.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  538.                         {
  539.                             if(Icon -> do_Type != WBTOOL)
  540.                             {
  541.                                 FreeDiskObject(Icon);
  542.  
  543.                                 Icon = NULL;
  544.                             }
  545.                         }
  546.  
  547.                         if(!Icon)
  548.                         {
  549.                             if(Icon = GetDiskObjectNew("term"))
  550.                             {
  551.                                 if(Icon -> do_Type != WBTOOL)
  552.                                 {
  553.                                     FreeDiskObject(Icon);
  554.  
  555.                                     Icon = NULL;
  556.                                 }
  557.                             }
  558.                         }
  559.  
  560.                         CurrentDir(OldLock);
  561.  
  562.                         UnLock(NewLock);
  563.                     }
  564.                 }
  565.             }
  566.         }
  567.     }
  568.  
  569.         /* Still no success. */
  570.  
  571.     if(!Icon)
  572.     {
  573.             /* Use the default names. */
  574.  
  575.         if(Icon = GetDiskObjectNew("term"))
  576.         {
  577.             if(Icon -> do_Type != WBTOOL)
  578.             {
  579.                 FreeDiskObject(Icon);
  580.  
  581.                 Icon = NULL;
  582.             }
  583.         }
  584.  
  585.         if(!Icon)
  586.         {
  587.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  588.             {
  589.                 if(Icon -> do_Type != WBTOOL)
  590.                 {
  591.                     FreeDiskObject(Icon);
  592.  
  593.                     Icon = NULL;
  594.                 }
  595.             }
  596.         }
  597.     }
  598.  
  599.     return(Icon);
  600. }
  601.  
  602.     /* GetPenIndex(LONG Pen):
  603.      *
  604.      *    Get the table index corresponding to an on-screen
  605.      *    text rendering pen.
  606.      */
  607.  
  608. LONG __regargs
  609. GetPenIndex(LONG Pen)
  610. {
  611.     LONG i;
  612.  
  613.     for(i = 0 ; i < 16 ; i++)
  614.     {
  615.         if(MappedPens[0][i] == Pen)
  616.             return(i);
  617.     }
  618. }
  619.  
  620.     /* GetScreenWidth(struct Window *Window):
  621.      *
  622.      *    Query the current screen width.
  623.      */
  624.  
  625. LONG __regargs
  626. GetScreenWidth(struct Window *Window)
  627. {
  628.     if(Window)
  629.     {
  630.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  631.             return(ScreenWidth);
  632.         else
  633.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  634.     }
  635.     else
  636.         return(ScreenWidth);
  637. }
  638.  
  639.     /* GetScreenHeight(struct Window *Window):
  640.      *
  641.      *    Query the current screen height.
  642.      */
  643.  
  644. LONG __regargs
  645. GetScreenHeight(struct Window *Window)
  646. {
  647.     if(Window)
  648.     {
  649.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  650.             return(ScreenHeight);
  651.         else
  652.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  653.     }
  654.     else
  655.         return(ScreenHeight);
  656. }
  657.  
  658.     /* GetLeft(struct Screen *Screen):
  659.      *
  660.      *    Get the screen left edge.
  661.      */
  662.  
  663. STATIC LONG __regargs
  664. GetLeft(struct Screen *Screen)
  665. {
  666.     if(Screen -> LeftEdge >= 0)
  667.         return(0);
  668.     else
  669.         return(-Screen -> LeftEdge);
  670. }
  671.  
  672.     /* GetScreenLeft(struct Window *Window):
  673.      *
  674.      *    Query the current screen left edge.
  675.      */
  676.  
  677. LONG __regargs
  678. GetScreenLeft(struct Window *Window)
  679. {
  680.     if(Window)
  681.     {
  682.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  683.             return(GetLeft(Window -> WScreen));
  684.         else
  685.             return(Window -> LeftEdge + Window -> BorderLeft);
  686.     }
  687.     else
  688.         return(GetLeft(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  689. }
  690.  
  691.     /* GetTop(struct Screen *Screen):
  692.      *
  693.      *    Get the screen top edge.
  694.      */
  695.  
  696. STATIC LONG __regargs
  697. GetTop(struct Screen *Screen)
  698. {
  699.     if(Screen -> TopEdge >= 0)
  700.         return(0);
  701.     else
  702.         return(-Screen -> TopEdge);
  703. }
  704.  
  705.     /* GetScreenTop(struct Window *Window):
  706.      *
  707.      *    Query the current screen top edge.
  708.      */
  709.  
  710. LONG __regargs
  711. GetScreenTop(struct Window *Window)
  712. {
  713.     if(Window)
  714.     {
  715.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  716.             return(GetTop(Window -> WScreen));
  717.         else
  718.             return(Window -> TopEdge + Window -> BorderTop);
  719.     }
  720.     else
  721.         return(GetTop(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  722. }
  723.  
  724.     /* OldGetAPen(struct RastPort *RPort):
  725.      *
  726.      *    Query the current primary rendering colour (old style).
  727.      */
  728.  
  729. ULONG
  730. OldGetAPen(struct RastPort *RPort)
  731. {
  732.     return((ULONG)RPort -> FgPen);
  733. }
  734.  
  735.     /* OldGetBPen(struct RastPort *RPort):
  736.      *
  737.      *    Query the current seconary rendering colour (old style).
  738.      */
  739.  
  740. ULONG
  741. OldGetBPen(struct RastPort *RPort)
  742. {
  743.     return((ULONG)RPort -> BgPen);
  744. }
  745.  
  746.     /* OldGetDrMd(struct RastPort *RPort):
  747.      *
  748.      *    Query the current drawing mode (old style).
  749.      */
  750.  
  751. ULONG
  752. OldGetDrMd(struct RastPort *RPort)
  753. {
  754.     return((ULONG)RPort -> DrawMode);
  755. }
  756.  
  757.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  758.      *
  759.      *    Set the rendering plane mask (old style).
  760.      */
  761.  
  762. ULONG
  763. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  764. {
  765.     if(UseMasking)
  766.         RPort -> Mask = Mask;
  767.  
  768.     return((ULONG)1);
  769. }
  770.  
  771.     /* NewGetAPen(struct RastPort *RPort):
  772.      *
  773.      *    Query the current primary rendering colour (new style).
  774.      */
  775.  
  776. ULONG
  777. NewGetAPen(struct RastPort *RPort)
  778. {
  779.     return(GetAPen(RPort));
  780. }
  781.  
  782.     /* NewGetBPen(struct RastPort *RPort):
  783.      *
  784.      *    Query the current seconary rendering colour (new style).
  785.      */
  786.  
  787. ULONG
  788. NewGetBPen(struct RastPort *RPort)
  789. {
  790.     return(GetBPen(RPort));
  791. }
  792.  
  793.     /* NewGetDrMd(struct RastPort *RPort):
  794.      *
  795.      *    Query the current drawing mode (new style).
  796.      */
  797.  
  798. ULONG
  799. NewGetDrMd(struct RastPort *RPort)
  800. {
  801.     return(GetDrMd(RPort));
  802. }
  803.  
  804.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  805.      *
  806.      *    Set the rendering plane mask (new style).
  807.      */
  808.  
  809. ULONG
  810. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  811. {
  812.     if(UseMasking)
  813.         return(SetWriteMask(RPort,Mask));
  814.     else
  815.         return((ULONG)1);
  816. }
  817.  
  818.     /* SetWait(struct Window *Window):
  819.      *
  820.      *    Set the busy wait mouse pointer.
  821.      */
  822.  
  823. VOID __regargs
  824. SetWait(struct Window *Window)
  825. {
  826.     if(Kick30)
  827.     {
  828.         SetWindowPointer(Window,
  829.             WA_BusyPointer,        TRUE,
  830.             WA_PointerDelay,    TRUE,
  831.         TAG_DONE);
  832.     }
  833.     else
  834.         SetPointer(Window,Stopwatch,16,16,-6,0);
  835. }
  836.  
  837.     /* ClrWait(struct Window *Window):
  838.      *
  839.      *    Remove the busy wait mouse pointer.
  840.      */
  841.  
  842. VOID __regargs
  843. ClrWait(struct Window *Window)
  844. {
  845.     if(Kick30)
  846.         SetWindowPointer(Window,TAG_DONE);
  847.     else
  848.         ClearPointer(Window);
  849. }
  850.  
  851.     /* GetModeName(ULONG Mode):
  852.      *
  853.      *    Get the name of a display mode.
  854.      */
  855.  
  856. STRPTR __regargs
  857. GetModeName(ULONG Mode)
  858. {
  859.     STATIC UBYTE __far    Buffer[DISPLAYNAMELEN + 1];
  860.     struct NameInfo        NameInfo;
  861.  
  862.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  863.         strcpy(Buffer,NameInfo . Name);
  864.     else
  865.     {
  866.         struct DimensionInfo DimensionInfo;
  867.  
  868.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  869.         {
  870.             STRPTR MonitorName;
  871.  
  872.             switch(Mode & MONITOR_ID_MASK)
  873.             {
  874.                 case NTSC_MONITOR_ID:
  875.  
  876.                     MonitorName = "NTSC: ";
  877.                     break;
  878.  
  879.                 case PAL_MONITOR_ID:
  880.  
  881.                     MonitorName = "PAL: ";
  882.                     break;
  883.  
  884.                 case VGA_MONITOR_ID:
  885.  
  886.                     MonitorName = "VGA: ";
  887.                     break;
  888.  
  889.                 case A2024_MONITOR_ID:
  890.  
  891.                     MonitorName = "A2024: ";
  892.                     break;
  893.  
  894.                 default:
  895.  
  896.                     MonitorName = "";
  897.                     break;
  898.             }
  899.  
  900.             SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  901.         }
  902.         else
  903.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  904.     }
  905.  
  906.     return(Buffer);
  907. }
  908.  
  909.     /* ModeOkay(ULONG ID):
  910.      *
  911.      *    Checks whether a display mode ID will do for deep
  912.      *    screen bitmaps.
  913.      */
  914.  
  915. BYTE __regargs
  916. ModeOkay(ULONG ID)
  917. {
  918.     struct DimensionInfo DimensionInfo;
  919.  
  920.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  921.     {
  922.         if(DimensionInfo . MaxDepth >= 4)
  923.             return(TRUE);
  924.     }
  925.  
  926.     return(FALSE);
  927. }
  928.  
  929.     /* SetClipMenu(BYTE Mode):
  930.      *
  931.      *    Enable/disable the copy/clear selection menu items.
  932.      */
  933.  
  934. VOID __regargs
  935. SetClipMenu(BYTE Mode)
  936. {
  937.     if(Mode && RasterEnabled)
  938.     {
  939.         OnItem(MEN_COPY);
  940.         OnItem(MEN_CLEAR);
  941.     }
  942.     else
  943.     {
  944.         OffItem(MEN_COPY);
  945.         OffItem(MEN_CLEAR);
  946.     }
  947. }
  948.  
  949.     /* SetRedialMenu():
  950.      *
  951.      *    Make the `redial' menu item available or make it
  952.      *    unavailable.
  953.      */
  954.  
  955. VOID
  956. SetRedialMenu()
  957. {
  958.     BYTE Mode;
  959.  
  960.     if(DialList)
  961.     {
  962.         if(DialList -> lh_Head -> ln_Succ)
  963.             Mode = TRUE;
  964.         else
  965.             Mode = FALSE;
  966.     }
  967.     else
  968.         Mode = FALSE;
  969.  
  970.     if(Mode && DialItemsAvailable)
  971.         OnItem(MEN_REDIAL);
  972.     else
  973.         OffItem(MEN_REDIAL);
  974. }
  975.  
  976.     /* SetDialMenu(BYTE Mode):
  977.      *
  978.      *    Block or enable the dialing menu.
  979.      */
  980.  
  981. VOID __regargs
  982. SetDialMenu(BYTE Mode)
  983. {
  984.     if(Window && Menu)
  985.     {
  986.         if(Mode)
  987.         {
  988.             if(DialList)
  989.             {
  990.                 if(DialList -> lh_Head -> ln_Succ)
  991.                     OnItem(MEN_REDIAL);
  992.                 else
  993.                     OffItem(MEN_REDIAL);
  994.             }
  995.             else
  996.                 OffItem(MEN_REDIAL);
  997.  
  998.             OnItem(MEN_DIAL_NUMBER);
  999.  
  1000.             if(FirstDialMenu != -1)
  1001.                 OnItem(MEN_EXTRA_DIAL);
  1002.         }
  1003.         else
  1004.         {
  1005.             OffItem(MEN_REDIAL);
  1006.             OffItem(MEN_DIAL_NUMBER);
  1007.  
  1008.             if(FirstDialMenu != -1)
  1009.                 OffItem(MEN_EXTRA_DIAL);
  1010.         }
  1011.  
  1012.         DialItemsAvailable = Mode;
  1013.     }
  1014. }
  1015.  
  1016.     /* SetTransferMenu(BYTE Mode):
  1017.      *
  1018.      *    Block or enable the transfer menu.
  1019.      */
  1020.  
  1021. VOID __regargs
  1022. SetTransferMenu(BYTE Mode)
  1023. {
  1024.     if(Window && Menu)
  1025.     {
  1026.         BOOLEAN    ValidDefault,
  1027.             ValidASCIIDownload,
  1028.             ValidASCIIUpload,
  1029.             ValidTextDownload,
  1030.             ValidTextUpload,
  1031.             ValidBinaryDownload,
  1032.             ValidBinaryUpload;
  1033.  
  1034.         if(!Config -> TransferConfig -> DefaultLibrary[0] || !Mode)
  1035.             ValidDefault = FALSE;
  1036.         else
  1037.             ValidDefault = TRUE;
  1038.  
  1039.         switch(Config -> TransferConfig -> ASCIIUploadType)
  1040.         {
  1041.             case XFER_INTERNAL:
  1042.  
  1043.                 ValidASCIIUpload = TRUE;
  1044.                 break;
  1045.  
  1046.             case XFER_DEFAULT:
  1047.  
  1048.                 ValidASCIIUpload = ValidDefault;
  1049.                 break;
  1050.  
  1051.             case XFER_XPR:
  1052.             case XFER_EXTERNALPROGRAM:
  1053.  
  1054.                 ValidASCIIUpload = Config -> TransferConfig -> ASCIIUploadLibrary[0];
  1055.                 break;
  1056.         }
  1057.  
  1058.         switch(Config -> TransferConfig -> ASCIIDownloadType)
  1059.         {
  1060.             case XFER_INTERNAL:
  1061.  
  1062.                 ValidASCIIDownload = TRUE;
  1063.                 break;
  1064.  
  1065.             case XFER_DEFAULT:
  1066.  
  1067.                 ValidASCIIDownload = ValidDefault;
  1068.                 break;
  1069.  
  1070.             case XFER_XPR:
  1071.             case XFER_EXTERNALPROGRAM:
  1072.  
  1073.                 ValidASCIIDownload = Config -> TransferConfig -> ASCIIDownloadLibrary[0];
  1074.                 break;
  1075.         }
  1076.  
  1077.  
  1078.         switch(Config -> TransferConfig -> TextUploadType)
  1079.         {
  1080.             case XFER_DEFAULT:
  1081.  
  1082.                 ValidTextUpload = ValidDefault;
  1083.                 break;
  1084.  
  1085.             case XFER_XPR:
  1086.             case XFER_EXTERNALPROGRAM:
  1087.  
  1088.                 ValidTextUpload = Config -> TransferConfig -> TextUploadLibrary[0];
  1089.                 break;
  1090.         }
  1091.  
  1092.         switch(Config -> TransferConfig -> TextDownloadType)
  1093.         {
  1094.             case XFER_DEFAULT:
  1095.  
  1096.                 ValidTextDownload = ValidDefault;
  1097.                 break;
  1098.  
  1099.             case XFER_XPR:
  1100.             case XFER_EXTERNALPROGRAM:
  1101.  
  1102.                 ValidTextDownload = Config -> TransferConfig -> TextDownloadLibrary[0];
  1103.                 break;
  1104.         }
  1105.  
  1106.         switch(Config -> TransferConfig -> BinaryUploadType)
  1107.         {
  1108.             case XFER_DEFAULT:
  1109.  
  1110.                 ValidBinaryUpload = ValidDefault;
  1111.                 break;
  1112.  
  1113.             case XFER_XPR:
  1114.             case XFER_EXTERNALPROGRAM:
  1115.  
  1116.                 ValidBinaryUpload = Config -> TransferConfig -> BinaryUploadLibrary[0];
  1117.                 break;
  1118.         }
  1119.  
  1120.         switch(Config -> TransferConfig -> BinaryDownloadType)
  1121.         {
  1122.             case XFER_DEFAULT:
  1123.  
  1124.                 ValidBinaryDownload = ValidDefault;
  1125.                 break;
  1126.  
  1127.             case XFER_XPR:
  1128.             case XFER_EXTERNALPROGRAM:
  1129.  
  1130.                 ValidBinaryDownload = Config -> TransferConfig -> BinaryDownloadLibrary[0];
  1131.                 break;
  1132.         }
  1133.  
  1134.         if(ValidASCIIUpload)
  1135.             OnItem(MEN_UPLOAD_ASCII);
  1136.         else
  1137.             OffItem(MEN_UPLOAD_ASCII);
  1138.  
  1139.         if(ValidASCIIDownload)
  1140.             OnItem(MEN_DOWNLOAD_ASCII);
  1141.         else
  1142.             OffItem(MEN_DOWNLOAD_ASCII);
  1143.  
  1144.         if(ValidTextUpload)
  1145.         {
  1146.             OnItem(MEN_UPLOAD_TEXT);
  1147.             OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1148.         }
  1149.         else
  1150.         {
  1151.             OffItem(MEN_UPLOAD_TEXT);
  1152.             OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1153.         }
  1154.  
  1155.         if(ValidTextDownload)
  1156.             OnItem(MEN_DOWNLOAD_TEXT);
  1157.         else
  1158.             OffItem(MEN_DOWNLOAD_TEXT);
  1159.  
  1160.         if(ValidBinaryUpload)
  1161.             OnItem(MEN_UPLOAD_BINARY);
  1162.         else
  1163.             OffItem(MEN_UPLOAD_BINARY);
  1164.  
  1165.         if(ValidBinaryDownload)
  1166.             OnItem(MEN_DOWNLOAD_BINARY);
  1167.         else
  1168.             OffItem(MEN_DOWNLOAD_BINARY);
  1169.  
  1170.         if(ValidDefault)
  1171.             OnItem(MEN_TRANSFER);
  1172.         else
  1173.             OffItem(MEN_TRANSFER);
  1174.     }
  1175. }
  1176.  
  1177.     /* SetRasterMenu(BYTE Mode):
  1178.      *
  1179.      *    Block or enable the menu entries associated with
  1180.      *    functions to access the screen raster.
  1181.      */
  1182.  
  1183. VOID __regargs
  1184. SetRasterMenu(BYTE Mode)
  1185. {
  1186.     if(Window && Menu)
  1187.     {
  1188.         if(Mode)
  1189.         {
  1190.             OnItem(MEN_SAVE_AS_TEXT);
  1191.             OnItem(MEN_PRINT_SCREEN);
  1192.         }
  1193.         else
  1194.         {
  1195.             OffItem(MEN_SAVE_AS_TEXT);
  1196.             OffItem(MEN_PRINT_SCREEN);
  1197.         }
  1198.     }
  1199. }
  1200.  
  1201.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced):
  1202.      *
  1203.      *    Pick a font using asl.library
  1204.      */
  1205.  
  1206. BYTE __regargs
  1207. PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced)
  1208. {
  1209.     struct FontRequester    *Requester;
  1210.     BYTE             Result = FALSE;
  1211.     LONG             Left    = 0,
  1212.                  Top    = 0,
  1213.                  Width    = 0,
  1214.                  Height    = 0;
  1215.  
  1216.     GetWindowInfo(WINDOW_FONT,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  1217.  
  1218.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  1219.         ASL_Window,                    Window,
  1220.         ASL_LeftEdge,                    Left,
  1221.         ASL_TopEdge,                    Top,
  1222.         ASL_Width,                    Width,
  1223.         ASL_Height,                    Height,
  1224.         ASLFO_InitialFrontPen,                DrawInfo -> dri_Pens[TEXTPEN],
  1225.         ASLFO_InitialBackPen,                DrawInfo -> dri_Pens[BACKGROUNDPEN],
  1226.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  1227.     TAG_DONE))
  1228.     {
  1229.         if(AslRequestTags(Requester,
  1230.             ASL_FontName,    Name,
  1231.             ASL_FontHeight,    *Points,
  1232.         TAG_DONE))
  1233.         {
  1234.             PutWindowInfo(WINDOW_FONT,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
  1235.  
  1236.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  1237.  
  1238.             *Points = Requester -> fo_Attr . ta_YSize;
  1239.  
  1240.             Result = TRUE;
  1241.         }
  1242.  
  1243.         FreeAslRequest(Requester);
  1244.     }
  1245.  
  1246.     return(Result);
  1247. }
  1248.  
  1249.     /* ExtractString():
  1250.      *
  1251.      *    Extracts a string from a list separated by `|' characters.
  1252.      */
  1253.  
  1254. STRPTR __regargs
  1255. ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
  1256. {
  1257.     STRPTR OldString;
  1258.  
  1259.     if(ReturnEnd)
  1260.         OldString = NULL;
  1261.     else
  1262.         OldString = String;
  1263.  
  1264.     while(*String)
  1265.     {
  1266.         if(*String == '|')
  1267.         {
  1268.             *Destination = 0;
  1269.  
  1270.             String++;
  1271.  
  1272.             if(*String)
  1273.                 return(String);
  1274.             else
  1275.                 return(OldString);
  1276.         }
  1277.         else
  1278.             *Destination++ = *String++;
  1279.     }
  1280.  
  1281.     *Destination = 0;
  1282.  
  1283.     return(OldString);
  1284. }
  1285.  
  1286.     /* GetListSize(struct List *List):
  1287.      *
  1288.      *    Determine the number of entries in a list.
  1289.      */
  1290.  
  1291. LONG __regargs
  1292. GetListSize(struct List *List)
  1293. {
  1294.     struct Node    *Node    = List -> lh_Head;
  1295.     LONG         i    = 0;
  1296.  
  1297.     while(Node -> ln_Succ)
  1298.     {
  1299.         i++;
  1300.  
  1301.         Node = Node -> ln_Succ;
  1302.     }
  1303.  
  1304.     return(i);
  1305. }
  1306.  
  1307.     /* GetListNode(LONG Offset,struct List *List):
  1308.      *
  1309.      *    Return the n-th Node entry in a standard exec list.
  1310.      */
  1311.  
  1312. struct Node * __regargs
  1313. GetListNode(LONG Offset,struct List *List)
  1314. {
  1315.     struct Node    *Node;
  1316.     LONG         i;
  1317.  
  1318.     Node = List -> lh_Head;
  1319.  
  1320.     for(i = 0 ; i < Offset ; i++)
  1321.     {
  1322.         if(!Node -> ln_Succ -> ln_Succ)
  1323.             return(NULL);
  1324.  
  1325.         Node = Node -> ln_Succ;
  1326.     }
  1327.  
  1328.     return(Node);
  1329. }
  1330.  
  1331.     /* CreateNode(STRPTR Name):
  1332.      *
  1333.      *    Put a name string into a list node.
  1334.      */
  1335.  
  1336. struct Node * __regargs
  1337. CreateNode(STRPTR Name)
  1338. {
  1339.     struct Node *Node;
  1340.  
  1341.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
  1342.     {
  1343.         Node -> ln_Name = (STRPTR)(Node + 1);
  1344.  
  1345.         strcpy(Node -> ln_Name,Name);
  1346.     }
  1347.  
  1348.     return(Node);
  1349. }
  1350.  
  1351.     /* FreeNode(struct Node *Node):
  1352.      *
  1353.      *    Remove and deallocate a node.
  1354.      */
  1355.  
  1356. VOID __regargs
  1357. FreeNode(struct Node *Node)
  1358. {
  1359.     Remove(Node);
  1360.  
  1361.     FreeVecPooled(Node);
  1362. }
  1363.  
  1364.     /* FreeList(struct List *List):
  1365.      *
  1366.      *    Remove all nodes from the list
  1367.      *    and free them on the way.
  1368.      */
  1369.  
  1370. VOID __regargs
  1371. FreeList(struct List *List)
  1372. {
  1373.     struct Node *Node,*NextNode;
  1374.  
  1375.     Node = List -> lh_Head;
  1376.  
  1377.     while(NextNode = Node -> ln_Succ)
  1378.     {
  1379.         FreeNode(Node);
  1380.  
  1381.         Node = NextNode;
  1382.     }
  1383. }
  1384.  
  1385.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1386.      *
  1387.      *    Scan a list for a certain node and return
  1388.      *    its position.
  1389.      */
  1390.  
  1391. LONG __regargs
  1392. GetNodeOffset(struct Node *Node,struct List *List)
  1393. {
  1394.     struct Node    *ListNode;
  1395.     LONG         Offset = 0;
  1396.  
  1397.     ListNode = List -> lh_Head;
  1398.  
  1399.     while(ListNode -> ln_Succ)
  1400.     {
  1401.         if(Node == ListNode)
  1402.             return(Offset);
  1403.         else
  1404.         {
  1405.             Offset++;
  1406.  
  1407.             ListNode = ListNode -> ln_Succ;
  1408.         }
  1409.     }
  1410.  
  1411.     return(~0);
  1412. }
  1413.  
  1414.     /* MoveList(struct List *From,struct List *To):
  1415.      *
  1416.      *    Move the contents of a list to a different list.
  1417.      */
  1418.  
  1419. VOID __regargs
  1420. MoveList(struct List *From,struct List *To)
  1421. {
  1422.     struct Node *Node,*NextNode;
  1423.  
  1424.     Node = From -> lh_Head;
  1425.  
  1426.     while(NextNode = Node -> ln_Succ)
  1427.     {
  1428.         Remove(Node);
  1429.  
  1430.         AddTail(To,Node);
  1431.  
  1432.         Node = NextNode;
  1433.     }
  1434. }
  1435.  
  1436.     /* LogAction(STRPTR String,...):
  1437.      *
  1438.      *    Write an action to the default log file.
  1439.      */
  1440.  
  1441. VOID __stdargs
  1442. LogAction(STRPTR String,...)
  1443. {
  1444.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  1445.     {
  1446.         UBYTE    DummyBuffer[512];
  1447.         BPTR    File;
  1448.  
  1449.         va_list    VarArgs;
  1450.  
  1451.             /* Build a valid string. */
  1452.  
  1453.         va_start(VarArgs,String);
  1454.         VSPrintf(DummyBuffer,String,VarArgs);
  1455.         va_end(VarArgs);
  1456.  
  1457.             /* Does the log file already exist? */
  1458.  
  1459.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  1460.         {
  1461.                 /* It does, let's append the data. */
  1462.  
  1463.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  1464.             {
  1465.                 if(Seek(File,0,OFFSET_END) == -1)
  1466.                 {
  1467.                     Close(File);
  1468.  
  1469.                     File = NULL;
  1470.                 }
  1471.             }
  1472.         }
  1473.         else
  1474.         {
  1475.                 /* Create a new file. */
  1476.  
  1477.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  1478.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1479.         }
  1480.  
  1481.             /* The file is open, build the date/time string and
  1482.              * write the log action.
  1483.              */
  1484.  
  1485.         if(File)
  1486.         {
  1487.             UBYTE        DateBuffer[40],
  1488.                     TimeBuffer[40];
  1489.             struct DateTime    DateTime;
  1490.  
  1491.             DateStamp(&DateTime . dat_Stamp);
  1492.  
  1493.             DateTime . dat_Format    = FORMAT_DOS;
  1494.             DateTime . dat_Flags    = NULL;
  1495.             DateTime . dat_StrDay    = NULL;
  1496.             DateTime . dat_StrDate    = DateBuffer;
  1497.             DateTime . dat_StrTime    = TimeBuffer;
  1498.  
  1499.             if(DateToStr(&DateTime))
  1500.             {
  1501.                 StripSpaces(TimeBuffer);
  1502.  
  1503.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1504.             }
  1505.  
  1506.                 /* Done! */
  1507.  
  1508.             Close(File);
  1509.         }
  1510.     }
  1511. }
  1512.  
  1513.     /* FlushMsg(struct Window *Window):
  1514.      *
  1515.      *    Cancel all pending messages of a window.
  1516.      */
  1517.  
  1518. VOID __regargs
  1519. FlushMsg(struct Window *Window)
  1520. {
  1521.     struct IntuiMessage *Massage;
  1522.  
  1523.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1524.         ReplyMsg(&Massage -> ExecMessage);
  1525. }
  1526.  
  1527.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1528.      *
  1529.      *    Get a string from the user, very much the same as xpr_gets,
  1530.      *    but also including the `Load File' gadget.
  1531.      */
  1532.  
  1533. BYTE __regargs
  1534. GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
  1535. {
  1536.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1537.  
  1538.     struct LayoutHandle    *Handle;
  1539.     BYTE             Success = FALSE;
  1540.     UBYTE             LocalBuffer[256];
  1541.  
  1542.     if(MaxChars > 255)
  1543.     {
  1544.         CopyMem(Buffer,LocalBuffer,255);
  1545.  
  1546.         LocalBuffer[255] = 0;
  1547.  
  1548.         MaxChars = 255;
  1549.     }
  1550.     else
  1551.         strcpy(LocalBuffer,Buffer);
  1552.  
  1553.     if(!Prompt)
  1554.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1555.  
  1556.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1557.         LH_LocaleHook,    &LocaleHook,
  1558.     TAG_DONE))
  1559.     {
  1560.         struct Window *PanelWindow;
  1561.  
  1562.         LT_New(Handle,
  1563.             LA_Type,    VERTICAL_KIND,
  1564.         TAG_DONE);
  1565.         {
  1566.             LT_New(Handle,
  1567.                 LA_Type,    VERTICAL_KIND,
  1568.                 LA_LabelText,    Prompt,
  1569.             TAG_DONE);
  1570.             {
  1571.                 if(Password)
  1572.                 {
  1573.                     LT_New(Handle,
  1574.                         LA_Type,    PASSWORD_KIND,
  1575.                         LA_STRPTR,    LocalBuffer,
  1576.                         LA_ID,        GAD_STRING,
  1577.                         LA_Chars,    40,
  1578.                         GTST_MaxChars,    MaxChars,
  1579.                     TAG_DONE);
  1580.                 }
  1581.                 else
  1582.                 {
  1583.                     LT_New(Handle,
  1584.                         LA_Type,    STRING_KIND,
  1585.                         LA_STRPTR,    LocalBuffer,
  1586.                         LA_ID,        GAD_STRING,
  1587.                         LA_Chars,    60,
  1588.                         LAST_Picker,    LoadGadget,
  1589.                     TAG_DONE);
  1590.                 }
  1591.  
  1592.                 LT_EndGroup(Handle);
  1593.             }
  1594.  
  1595.             LT_New(Handle,
  1596.                 LA_Type,VERTICAL_KIND,
  1597.             TAG_DONE);
  1598.             {
  1599.                 LT_New(Handle,
  1600.                     LA_Type,    XBAR_KIND,
  1601.                     LAXB_FullSize,    TRUE,
  1602.                 TAG_DONE);
  1603.  
  1604.                 LT_EndGroup(Handle);
  1605.             }
  1606.  
  1607.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1608.                 LAGR_SameSize,    TRUE,
  1609.                 LAGR_Spread,    TRUE,
  1610.             TAG_DONE);
  1611.             {
  1612.                 LT_New(Handle,
  1613.                     LA_Type,    BUTTON_KIND,
  1614.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1615.                     LA_ID,        GAD_OK,
  1616.                     LABT_ReturnKey,    TRUE,
  1617.                     LABT_ExtraFat,    TRUE,
  1618.                 TAG_DONE);
  1619.  
  1620.                 LT_New(Handle,
  1621.                     LA_Type,    BUTTON_KIND,
  1622.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1623.                     LA_ID,        GAD_CANCEL,
  1624.                     LABT_EscKey,    TRUE,
  1625.                     LABT_ExtraFat,    TRUE,
  1626.                 TAG_DONE);
  1627.  
  1628.                 LT_EndGroup(Handle);
  1629.             }
  1630.         }
  1631.  
  1632.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1633.             LAWN_HelpHook,        &GuideHook,
  1634.             LAWN_Parent,        Window,
  1635.             WA_DepthGadget,        TRUE,
  1636.             WA_CloseGadget,        TRUE,
  1637.             WA_DragBar,        TRUE,
  1638.             WA_RMBTrap,        TRUE,
  1639.             WA_Activate,        TRUE,
  1640.         TAG_DONE))
  1641.         {
  1642.             struct IntuiMessage    *Message;
  1643.             BOOLEAN             Done = FALSE;
  1644.             ULONG             MsgClass,
  1645.                          MsgQualifier;
  1646.             UWORD             MsgCode;
  1647.             struct Gadget        *MsgGadget;
  1648.  
  1649.             LT_Activate(Handle,GAD_STRING);
  1650.  
  1651.             PushWindow(PanelWindow);
  1652.  
  1653.             LT_ShowWindow(Handle,TRUE);
  1654.  
  1655.             do
  1656.             {
  1657.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1658.                     break;
  1659.  
  1660.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  1661.                 {
  1662.                     MsgClass    = Message -> Class;
  1663.                     MsgQualifier    = Message -> Qualifier;
  1664.                     MsgCode        = Message -> Code;
  1665.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1666.  
  1667.                     GT_ReplyIMsg(Message);
  1668.  
  1669.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1670.  
  1671.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1672.                         Done = TRUE;
  1673.  
  1674.                     if(MsgClass == IDCMP_GADGETUP)
  1675.                     {
  1676.                         switch(MsgGadget -> GadgetID)
  1677.                         {
  1678.                             case GAD_STRING:
  1679.  
  1680.                                 if(MsgCode == '\r')
  1681.                                 {
  1682.                                     strcpy(Buffer,LocalBuffer);
  1683.  
  1684.                                     Success = Done = TRUE;
  1685.  
  1686.                                     LT_PressButton(Handle,GAD_OK);
  1687.                                 }
  1688.  
  1689.                                 break;
  1690.  
  1691.                             case GAD_OK:
  1692.  
  1693.                                 LT_UpdateStrings(Handle);
  1694.  
  1695.                                 strcpy(Buffer,LocalBuffer);
  1696.  
  1697.                                 Success = Done = TRUE;
  1698.                                 break;
  1699.  
  1700.                             case GAD_CANCEL:
  1701.  
  1702.                                 Done = TRUE;
  1703.                                 break;
  1704.                         }
  1705.                     }
  1706.  
  1707.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
  1708.                     {
  1709.                         UBYTE             DummyBuffer[MAX_FILENAME_LENGTH],
  1710.                                     *DummyChar;
  1711.                         struct FileRequester    *FileRequest;
  1712.  
  1713.                         LT_LockWindow(PanelWindow);
  1714.  
  1715.                         SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
  1716.  
  1717.                         if(FileRequest = GetFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  1718.                         {
  1719.                             LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
  1720.  
  1721.                             FreeAslRequest(FileRequest);
  1722.                         }
  1723.  
  1724.                         LT_UnlockWindow(PanelWindow);
  1725.                     }
  1726.                 }
  1727.             }
  1728.             while(!Done);
  1729.  
  1730.             PopWindow();
  1731.         }
  1732.  
  1733.         LT_DeleteHandle(Handle);
  1734.     }
  1735.  
  1736.     return(Success);
  1737. }
  1738.  
  1739.     /* WakeUp(struct Window *Window,WORD Sound):
  1740.      *
  1741.      *    Pop a window to the front and alert the user.
  1742.      */
  1743.  
  1744. VOID __regargs
  1745. WakeUp(struct Window *Window,WORD Sound)
  1746. {
  1747.     if(Window)
  1748.     {
  1749.         if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1750.         {
  1751.             if(Window -> WScreen -> LeftEdge > 0)
  1752.             {
  1753.                 if(Window -> WScreen -> TopEdge > 0)
  1754.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1755.                 else
  1756.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1757.             }
  1758.             else
  1759.             {
  1760.                 if(Window -> WScreen -> TopEdge > 0)
  1761.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1762.             }
  1763.  
  1764.             WindowToFront(Window);
  1765.  
  1766.             ScreenToFront(Window -> WScreen);
  1767.         }
  1768.     }
  1769.  
  1770.     if(Sound != SOUND_BELL || Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1771.         SoundPlay(Sound);
  1772. }
  1773.  
  1774.     /* TaskDestructor(struct DataMsg *Item):
  1775.      *
  1776.      *    Msg destructor for the routines below.
  1777.      */
  1778.  
  1779. STATIC VOID __stdargs
  1780. TaskDestructor(struct DataMsg *Item)
  1781. {
  1782.     Signal((struct Process *)Item -> Data,SIGBREAKF_CTRL_F);
  1783. }
  1784.  
  1785.     /* AmigaDOSBackgroundServer(VOID):
  1786.      *
  1787.      *    Background process to handle tool execution.
  1788.      */
  1789.  
  1790. STATIC VOID __saveds
  1791. AmigaDOSBackgroundServer(VOID)
  1792. {
  1793.     BPTR         OldCOS,
  1794.              NewCOS = NULL;
  1795.     struct DataMsg     Msg;
  1796.     STRPTR         Command;
  1797.     struct Process    *Me;
  1798.  
  1799.         /* Look who we are. */
  1800.  
  1801.     Me = (struct Process *)SysBase -> ThisTask;
  1802.  
  1803.     Command = Me -> pr_Task . tc_UserData;
  1804.  
  1805.         /* Create console output stream, will be closed automagically on exit. */
  1806.  
  1807.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1808.     {
  1809.         if(NewCOS = Open("*",MODE_NEWFILE))
  1810.         {
  1811.             OldCOS = Me -> pr_COS;
  1812.  
  1813.             Me -> pr_COS = NewCOS;
  1814.         }
  1815.     }
  1816.  
  1817.     SystemTags(Command,
  1818.         SYS_UserShell,    TRUE,
  1819.     TAG_DONE);
  1820.  
  1821.     FreeVecPooled(Command);
  1822.  
  1823.     Forbid();
  1824.  
  1825.     InitMsgItem(&Msg,TaskDestructor);
  1826.  
  1827.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1828.     Msg . Data = (UBYTE *)Me;
  1829.  
  1830.     ClrSignal(SIGBREAKF_CTRL_F);
  1831.  
  1832.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1833.  
  1834.     Wait(SIGBREAKF_CTRL_F);
  1835.  
  1836.     if(NewCOS)
  1837.     {
  1838.         Me -> pr_COS = OldCOS;
  1839.  
  1840.         Close(NewCOS);
  1841.     }
  1842. }
  1843.  
  1844.     /* SendAmigaDOSCommand(STRPTR Name):
  1845.      *
  1846.      *    Let the current default Shell execute an AmigaDOS
  1847.      *    command. Block until the command has returned.
  1848.      */
  1849.  
  1850. VOID __regargs
  1851. SendAmigaDOSCommand(STRPTR Name)
  1852. {
  1853.     STRPTR NewName;
  1854.  
  1855.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1856.     {
  1857.         struct Process    *NewProcess;
  1858.         BPTR         Stream;
  1859.         STRPTR         NewWindowName;
  1860.  
  1861.         strcpy(NewName,Name);
  1862.  
  1863.         NewWindowName = NewName + strlen(NewName) + 1;
  1864.  
  1865.         BlockWindows();
  1866.  
  1867.         SetQueueDiscard(SpecialQueue,FALSE);
  1868.  
  1869.             /* Open the output file. */
  1870.  
  1871.         if(WindowName[0])
  1872.         {
  1873.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1874.  
  1875.             if(Window)
  1876.             {
  1877.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1878.                     LocalName[0] = 0;
  1879.             }
  1880.  
  1881.             if(LocalName[0])
  1882.             {
  1883.                 SPrintf(NewWindowName,WindowName,LocalName);
  1884.  
  1885.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1886.             }
  1887.             else
  1888.                 Stream = Open(WindowName,MODE_NEWFILE);
  1889.         }
  1890.         else
  1891.             Stream = NULL;
  1892.  
  1893.         Forbid();
  1894.  
  1895.         if(Stream)
  1896.         {
  1897.             if(GoodStream(Stream))
  1898.             {
  1899.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1900.  
  1901.                 NewProcess = (struct Process *)CreateNewProcTags(
  1902.                     NP_Entry,    AmigaDOSBackgroundServer,
  1903.                     NP_Name,    "term AmigaDOS Background Process",
  1904.                     NP_Input,    Stream,
  1905.                     NP_Output,    NULL,
  1906.                     NP_Cli,        TRUE,
  1907.                     NP_ConsoleTask,    Handle -> fh_Type,
  1908.                     NP_StackSize,    16384,
  1909.                 TAG_END);
  1910.             }
  1911.             else
  1912.             {
  1913.                 NewProcess = (struct Process *)CreateNewProcTags(
  1914.                     NP_Entry,    AmigaDOSBackgroundServer,
  1915.                     NP_Name,    "term AmigaDOS Background Process",
  1916.                     NP_Output,    Stream,
  1917.                     NP_Cli,        TRUE,
  1918.                     NP_ConsoleTask,    NULL,
  1919.                     NP_StackSize,    16384,
  1920.                 TAG_END);
  1921.             }
  1922.         }
  1923.         else
  1924.         {
  1925.             NewProcess = (struct Process *)CreateNewProcTags(
  1926.                 NP_Entry,    AmigaDOSBackgroundServer,
  1927.                 NP_Name,    "term AmigaDOS Background Process",
  1928.                 NP_Cli,        TRUE,
  1929.                 NP_ConsoleTask,    NULL,
  1930.                 NP_StackSize,    16384,
  1931.             TAG_END);
  1932.         }
  1933.  
  1934.             /* Did we succeed in creating the process? */
  1935.  
  1936.         if(NewProcess)
  1937.         {
  1938.             CantQuit++;
  1939.  
  1940.             NewProcess -> pr_Task . tc_UserData = NewName;
  1941.  
  1942.             Permit();
  1943.         }
  1944.         else
  1945.         {
  1946.             Permit();
  1947.  
  1948.             if(Stream)
  1949.                 Close(Stream);
  1950.  
  1951.             FreeVecPooled(NewName);
  1952.  
  1953.             BumpWindow(Window);
  1954.  
  1955.             ReleaseWindows();
  1956.         }
  1957.     }
  1958. }
  1959.  
  1960.     /* RexxBackgroundServer():
  1961.      *
  1962.      *    The background process to handle the rexx
  1963.      *    massaging.
  1964.      */
  1965.  
  1966. STATIC VOID __saveds
  1967. RexxBackgroundServer(VOID)
  1968. {
  1969.     struct MsgPort     *RexxPort;
  1970.     BPTR         OldCOS,
  1971.              NewCOS = NULL;
  1972.     struct DataMsg     Msg;
  1973.     STRPTR         Command;
  1974.     struct Process    *Me;
  1975.  
  1976.         /* Look who we are. */
  1977.  
  1978.     Me = (struct Process *)SysBase -> ThisTask;
  1979.  
  1980.     Command = Me -> pr_Task . tc_UserData;
  1981.  
  1982.         /* Create console output stream, will be closed automagically on exit. */
  1983.  
  1984.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1985.     {
  1986.         if(NewCOS = Open("*",MODE_NEWFILE))
  1987.         {
  1988.             OldCOS = Me -> pr_COS;
  1989.  
  1990.             Me -> pr_COS = NewCOS;
  1991.         }
  1992.     }
  1993.  
  1994.     if(RexxPort = FindPort(RXSDIR))
  1995.     {
  1996.         struct MsgPort __aligned     ReplyPort;
  1997.         struct RexxMsg            *RexxMsg;
  1998.  
  1999.         InitSinglePort(&ReplyPort);
  2000.  
  2001.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  2002.         {
  2003.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
  2004.             {
  2005.                 RexxMsg -> rm_Action = RXCOMM;
  2006.  
  2007.                 Forbid();
  2008.  
  2009.                 ClrSignal(SIGF_SINGLE);
  2010.  
  2011.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  2012.  
  2013.                 WaitPort(&ReplyPort);
  2014.  
  2015.                 GetMsg(&ReplyPort);
  2016.  
  2017.                 Permit();
  2018.  
  2019.                     /* This doesn't look too
  2020.                      * good, does it?
  2021.                      */
  2022.  
  2023.                 if(RexxMsg -> rm_Result1 && Me -> pr_COS)
  2024.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  2025.  
  2026.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  2027.             }
  2028.  
  2029.             DeleteRexxMsg(RexxMsg);
  2030.         }
  2031.     }
  2032.  
  2033.     FreeVecPooled(Command);
  2034.  
  2035.     Forbid();
  2036.  
  2037.     InitMsgItem(&Msg,TaskDestructor);
  2038.  
  2039.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  2040.     Msg . Data = (UBYTE *)Me;
  2041.  
  2042.     ClrSignal(SIGBREAKF_CTRL_F);
  2043.  
  2044.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  2045.  
  2046.     Wait(SIGBREAKF_CTRL_F);
  2047.  
  2048.     if(NewCOS)
  2049.     {
  2050.         Me -> pr_COS = OldCOS;
  2051.  
  2052.         Close(NewCOS);
  2053.     }
  2054. }
  2055.  
  2056.     /* SendARexxCommand(STRPTR Name,BOOL QueueIt):
  2057.      *
  2058.      *    Let the ARexx server execute a command (or a script
  2059.      *    file if necessary) and block until the command
  2060.      *    has returned.
  2061.      */
  2062.  
  2063. VOID __regargs
  2064. SendARexxCommand(STRPTR Name,BOOL QueueIt)
  2065. {
  2066.     STRPTR NewName;
  2067.  
  2068.     if(QueueIt)
  2069.     {
  2070.         ObtainSemaphore(&ARexxQueueSemaphore);
  2071.  
  2072.         if(ARexxRunning)
  2073.         {
  2074.             struct Node *Node;
  2075.  
  2076.             if(Node = CreateNode(Name))
  2077.                 AddTail(&ARexxQueue,Node);
  2078.  
  2079.             ReleaseSemaphore(&ARexxQueueSemaphore);
  2080.  
  2081.             return;
  2082.         }
  2083.     }
  2084.  
  2085.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  2086.     {
  2087.         struct Process    *NewProcess;
  2088.         BPTR         Stream;
  2089.         STRPTR         NewWindowName;
  2090.  
  2091.         strcpy(NewName,Name);
  2092.  
  2093.         NewWindowName = NewName + strlen(NewName) + 1;
  2094.  
  2095.         BlockWindows();
  2096.  
  2097.         SetQueueDiscard(SpecialQueue,FALSE);
  2098.  
  2099.             /* Open the output file. */
  2100.  
  2101.         if(WindowName[0])
  2102.         {
  2103.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  2104.  
  2105.             if(Window)
  2106.             {
  2107.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  2108.                     LocalName[0] = 0;
  2109.             }
  2110.  
  2111.             if(LocalName[0])
  2112.             {
  2113.                 SPrintf(NewWindowName,WindowName,LocalName);
  2114.  
  2115.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  2116.             }
  2117.             else
  2118.                 Stream = Open(WindowName,MODE_NEWFILE);
  2119.         }
  2120.         else
  2121.             Stream = NULL;
  2122.  
  2123.         Forbid();
  2124.  
  2125.             /* Create the background process which will
  2126.              * handle all the messy rexx message sending
  2127.              * for us.
  2128.              */
  2129.  
  2130.         if(Stream)
  2131.         {
  2132.             if(GoodStream(Stream))
  2133.             {
  2134.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  2135.  
  2136.                 NewProcess = (struct Process *)CreateNewProcTags(
  2137.                     NP_Entry,    RexxBackgroundServer,
  2138.                     NP_Name,    "term ARexx Background Process",
  2139.                     NP_Input,    Stream,
  2140.                     NP_Output,    NULL,
  2141.                     NP_Cli,        TRUE,
  2142.                     NP_ConsoleTask,    Handle -> fh_Type,
  2143.                     NP_StackSize,    16384,
  2144.                 TAG_END);
  2145.             }
  2146.             else
  2147.             {
  2148.                 NewProcess = (struct Process *)CreateNewProcTags(
  2149.                     NP_Entry,    RexxBackgroundServer,
  2150.                     NP_Name,    "term ARexx Background Process",
  2151.                     NP_Output,    Stream,
  2152.                     NP_Cli,        TRUE,
  2153.                     NP_ConsoleTask,    NULL,
  2154.                     NP_StackSize,    16384,
  2155.                 TAG_END);
  2156.             }
  2157.         }
  2158.         else
  2159.         {
  2160.             NewProcess = (struct Process *)CreateNewProcTags(
  2161.                 NP_Entry,    RexxBackgroundServer,
  2162.                 NP_Name,    "term ARexx Background Process",
  2163.                 NP_Cli,        TRUE,
  2164.                 NP_ConsoleTask,    NULL,
  2165.                 NP_StackSize,    16384,
  2166.             TAG_END);
  2167.         }
  2168.  
  2169.             /* Did we succeed in creating the process? */
  2170.  
  2171.         if(NewProcess)
  2172.         {
  2173.             CantQuit++;
  2174.  
  2175.             NewProcess -> pr_Task . tc_UserData = NewName;
  2176.  
  2177.             Permit();
  2178.  
  2179.             if(QueueIt)
  2180.                 ARexxRunning = TRUE;
  2181.         }
  2182.         else
  2183.         {
  2184.             Permit();
  2185.  
  2186.             if(Stream)
  2187.                 Close(Stream);
  2188.  
  2189.             FreeVecPooled(NewName);
  2190.  
  2191.             BumpWindow(Window);
  2192.  
  2193.             ReleaseWindows();
  2194.         }
  2195.     }
  2196.  
  2197.     if(QueueIt)
  2198.         ReleaseSemaphore(&ARexxQueueSemaphore);
  2199. }
  2200.  
  2201.     /* BlockWindows():
  2202.      *
  2203.      *    Block the main window and the status window (i.e. disable
  2204.      *    the menu and attach a wait pointer).
  2205.      */
  2206.  
  2207. VOID
  2208. BlockWindows()
  2209. {
  2210.     if(!(BlockNestCount++))
  2211.     {
  2212.         LT_LockWindow(Window);
  2213.         LT_LockWindow(StatusWindow);
  2214.         LT_LockWindow(FastWindow);
  2215.  
  2216.         WeAreBlocking = TRUE;
  2217.  
  2218.         SetQueueDiscard(SpecialQueue,TRUE);
  2219.  
  2220.         GhostCursor();
  2221.     }
  2222. }
  2223.  
  2224.     /* ReleaseWindows():
  2225.      *
  2226.      *    Reenable the menus and clear the wait pointer.
  2227.      */
  2228.  
  2229. VOID
  2230. ReleaseWindows()
  2231. {
  2232.     if(BlockNestCount == 1)
  2233.     {
  2234.         LT_UnlockWindow(Window);
  2235.         LT_UnlockWindow(StatusWindow);
  2236.         LT_UnlockWindow(FastWindow);
  2237.  
  2238.         WeAreBlocking = FALSE;
  2239.  
  2240.         SetQueueDiscard(SpecialQueue,FALSE);
  2241.  
  2242.         if(Window)
  2243.         {
  2244.             Forbid();
  2245.  
  2246.             if(Window -> Flags & WFLG_WINDOWACTIVE)
  2247.                 NormalCursor();
  2248.  
  2249.             Permit();
  2250.         }
  2251.     }
  2252.  
  2253.     if(BlockNestCount)
  2254.         BlockNestCount--;
  2255. }
  2256.  
  2257.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  2258.      *
  2259.      *    Read a few bytes from a file (à la gets).
  2260.      */
  2261.  
  2262. LONG __regargs
  2263. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  2264. {
  2265.     STATIC UBYTE __far    Data[1024];
  2266.     STATIC LONG        ReadIndex    = 0,
  2267.                 ReadLen        = 0;
  2268.  
  2269.     if(File)
  2270.     {
  2271.         LONG BytesRead = 0,i;
  2272.  
  2273.         for(i = 0 ; i < MaxChars ; i++)
  2274.         {
  2275.             if(ReadIndex >= ReadLen)
  2276.             {
  2277.                 ReadLen = Read(File,Data,1024);
  2278.  
  2279.                 ReadIndex = 0;
  2280.  
  2281.                 if(ReadLen <= 0)
  2282.                 {
  2283.                     Buffer[i] = 0;
  2284.  
  2285.                     return(BytesRead);
  2286.                 }
  2287.             }
  2288.  
  2289.             BytesRead++;
  2290.  
  2291.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  2292.             {
  2293.                 Buffer[i + 1] = 0;
  2294.  
  2295.                 return(BytesRead);
  2296.             }
  2297.         }
  2298.  
  2299.         return(BytesRead);
  2300.     }
  2301.     else
  2302.         ReadIndex = ReadLen = 0;
  2303. }
  2304.  
  2305.     /* GetBaudRate(STRPTR Buffer):
  2306.      *
  2307.      *    Calculate the baud rate contained in a connect string.
  2308.      */
  2309.  
  2310. LONG __regargs
  2311. GetBaudRate(STRPTR Buffer)
  2312. {
  2313.     LONG Rate,i,j;
  2314.  
  2315.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  2316.     {
  2317.         if(Buffer[i] == ' ')
  2318.             continue;
  2319.         else
  2320.         {
  2321.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  2322.                 SharedBuffer[j++] = Buffer[i];
  2323.             else
  2324.                 break;
  2325.         }
  2326.     }
  2327.  
  2328.     SharedBuffer[j] = 0;
  2329.  
  2330.     if(StrToLong(SharedBuffer,&Rate) > 0)
  2331.     {
  2332.         if(Rate > 0)
  2333.             return(Rate);
  2334.     }
  2335.  
  2336.     return(0);
  2337. }
  2338.  
  2339.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  2340.      *
  2341.      *    Auxilary routine for FindThisItem(), scans
  2342.      *    menu item and sub item lists.
  2343.      */
  2344.  
  2345. STATIC struct MenuItem * __inline
  2346. LookForIt(struct MenuItem *Item,ULONG ID)
  2347. {
  2348.     while(Item)
  2349.     {
  2350.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  2351.             return(Item);
  2352.         else
  2353.         {
  2354.             if(Item -> SubItem)
  2355.             {
  2356.                 register struct MenuItem *TheItem;
  2357.  
  2358.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  2359.                     return(TheItem);
  2360.             }
  2361.  
  2362.             Item = Item -> NextItem;
  2363.         }
  2364.     }
  2365.  
  2366.     return(NULL);
  2367. }
  2368.  
  2369.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  2370.      *
  2371.      *    Scan a menu for a menuitem associated with a
  2372.      *    menu ID.
  2373.      */
  2374.  
  2375. struct MenuItem * __regargs
  2376. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  2377. {
  2378.     if(TypeOfMem(FirstMenu))
  2379.     {
  2380.         struct MenuItem *Item;
  2381.  
  2382.         while(FirstMenu)
  2383.         {
  2384.             if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  2385.                 return(Item);
  2386.             else
  2387.                 FirstMenu = FirstMenu -> NextMenu;
  2388.         }
  2389.     }
  2390.  
  2391.     return(NULL);
  2392. }
  2393.  
  2394. struct Menu * __regargs
  2395. FindThisMenu(struct Menu *FirstMenu,ULONG MenuID)
  2396. {
  2397.     if(TypeOfMem(FirstMenu))
  2398.     {
  2399.         while(FirstMenu)
  2400.         {
  2401.             if(GTMENU_USERDATA(FirstMenu) == (APTR)MenuID)
  2402.                 return(FirstMenu);
  2403.             else
  2404.                 FirstMenu = FirstMenu -> NextMenu;
  2405.         }
  2406.     }
  2407.  
  2408.     return(NULL);
  2409. }
  2410.  
  2411.     /* GetItem(ULONG MenuID):
  2412.      *
  2413.      *    Get the checkmark state of a menu item.
  2414.      */
  2415.  
  2416. BYTE __regargs
  2417. GetItem(ULONG MenuID)
  2418. {
  2419.     if(Menu)
  2420.     {
  2421.         struct MenuItem *Item;
  2422.  
  2423.         if(Item = FindThisItem(Menu,MenuID))
  2424.         {
  2425.             if(Item -> Flags & CHECKED)
  2426.                 return(TRUE);
  2427.         }
  2428.     }
  2429.  
  2430.     return(FALSE);
  2431. }
  2432.  
  2433.     /* SetItem(ULONG MenuID,BYTE Mode):
  2434.      *
  2435.      *    Clear or set the checkmark or state of a menu item.
  2436.      */
  2437.  
  2438. VOID __regargs
  2439. SetItem(ULONG MenuID,BYTE Mode)
  2440. {
  2441.         /* Is the global pull-down menu available? */
  2442.  
  2443.     if(Menu)
  2444.     {
  2445.         struct MenuItem    *Item;
  2446.         struct Menu    *ThisMenu;
  2447.  
  2448.         if(ThisMenu = FindThisMenu(Menu,MenuID))
  2449.         {
  2450.                 /* Remove the menu from the windows. */
  2451.  
  2452.             if(Window)
  2453.                 ClearMenuStrip(Window);
  2454.  
  2455.             if(StatusWindow)
  2456.                 ClearMenuStrip(StatusWindow);
  2457.  
  2458.             if(FastWindow)
  2459.                 ClearMenuStrip(FastWindow);
  2460.  
  2461.             switch(Mode)
  2462.             {
  2463.                 case SETITEM_ON:
  2464.  
  2465.                     ThisMenu -> Flags |= MENUENABLED;
  2466.                     break;
  2467.  
  2468.                 case SETITEM_OFF:
  2469.  
  2470.                     ThisMenu -> Flags &= ~MENUENABLED;
  2471.                     break;
  2472.             }
  2473.  
  2474.                 /* Reattach the menu to the windows. */
  2475.  
  2476.             if(Window)
  2477.                 ResetMenuStrip(Window,Menu);
  2478.  
  2479.             if(StatusWindow)
  2480.                 ResetMenuStrip(StatusWindow,Menu);
  2481.  
  2482.             if(FastWindow)
  2483.                 ResetMenuStrip(FastWindow,Menu);
  2484.  
  2485.             return;
  2486.         }
  2487.  
  2488.             /* Try to find the menu item and change
  2489.              * the state of the checkmark.
  2490.              */
  2491.  
  2492.         if(Item = FindThisItem(Menu,MenuID))
  2493.         {
  2494.                 /* Remove the menu from the windows. */
  2495.  
  2496.             if(Window)
  2497.                 ClearMenuStrip(Window);
  2498.  
  2499.             if(StatusWindow)
  2500.                 ClearMenuStrip(StatusWindow);
  2501.  
  2502.             if(FastWindow)
  2503.                 ClearMenuStrip(FastWindow);
  2504.  
  2505.             switch(Mode)
  2506.             {
  2507.                 case SETITEM_SETCHECK:
  2508.  
  2509.                     Item -> Flags |= CHECKED;
  2510.                     break;
  2511.  
  2512.                 case SETITEM_CLRCHECK:
  2513.  
  2514.                     Item -> Flags &= ~CHECKED;
  2515.                     break;
  2516.  
  2517.                 case SETITEM_ON:
  2518.  
  2519.                     Item -> Flags |= ITEMENABLED;
  2520.                     break;
  2521.  
  2522.                 case SETITEM_OFF:
  2523.  
  2524.                     Item -> Flags &= ~ITEMENABLED;
  2525.                     break;
  2526.             }
  2527.  
  2528.                 /* Reattach the menu to the windows. */
  2529.  
  2530.             if(Window)
  2531.                 ResetMenuStrip(Window,Menu);
  2532.  
  2533.             if(StatusWindow)
  2534.                 ResetMenuStrip(StatusWindow,Menu);
  2535.  
  2536.             if(FastWindow)
  2537.                 ResetMenuStrip(FastWindow,Menu);
  2538.         }
  2539.     }
  2540. }
  2541.  
  2542.     /* GetFileSize(STRPTR Name):
  2543.      *
  2544.      *    Simple routine to return the size of a file in
  2545.      *    bytes.
  2546.      */
  2547.  
  2548. LONG __regargs
  2549. GetFileSize(STRPTR Name)
  2550. {
  2551.     struct FileInfoBlock    *FileInfo;
  2552.     LONG             FileSize = 0;
  2553.  
  2554.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2555.     {
  2556.         BPTR FileLock;
  2557.  
  2558.         if(FileLock = Lock(Name,ACCESS_READ))
  2559.         {
  2560.             if(Examine(FileLock,FileInfo))
  2561.             {
  2562.                 if(FileInfo -> fib_DirEntryType < 0)
  2563.                     FileSize = FileInfo -> fib_Size;
  2564.             }
  2565.  
  2566.             UnLock(FileLock);
  2567.         }
  2568.  
  2569.         FreeDosObject(DOS_FIB,FileInfo);
  2570.     }
  2571.  
  2572.     return(FileSize);
  2573. }
  2574.  
  2575.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
  2576.      *
  2577.      *    Call the asl.library file requester to select a single or
  2578.      *    a couple of files.
  2579.      */
  2580.  
  2581. struct FileRequester * __regargs
  2582. GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText,BYTE AskWrite)
  2583. {
  2584.     STATIC UBYTE __far     DirBuffer[MAX_FILENAME_LENGTH],
  2585.                  PatternBuffer[60];
  2586.  
  2587.     struct FileRequester    *AslFileRequest;
  2588.     BYTE             Result        = FALSE,
  2589.                  DefaultPattern    = FALSE;
  2590.     LONG             Flags,ExtFlags = 0;
  2591.     WORD             i,j;
  2592.  
  2593.     UBYTE             OtherTitle[60];
  2594.     LONG             Left    = 0,
  2595.                  Top    = 0,
  2596.                  Width    = 0,
  2597.                  Height    = 0;
  2598.  
  2599.     if(!Config -> MiscConfig -> ProtectiveMode)
  2600.         AskWrite = FALSE;
  2601.  
  2602.     if(!Parent)
  2603.         Parent = Window;
  2604.  
  2605.     for(i = j = 0 ; i < strlen(Title) ; i++)
  2606.     {
  2607.         if(Title[i] != '_')
  2608.             OtherTitle[j++] = Title[i];
  2609.     }
  2610.  
  2611.     OtherTitle[j] = 0;
  2612.  
  2613.     Title = OtherTitle;
  2614.  
  2615.     if(DirsOnly)
  2616.     {
  2617.         ExtFlags |= FIL1F_NOFILES;
  2618.  
  2619.         if(Pattern)
  2620.             ExtFlags |= FIL1F_MATCHDIRS;
  2621.     }
  2622.  
  2623.     GetWindowInfo(WINDOW_FILE,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  2624.  
  2625.         /* Empty directory string? Revert to the last directory
  2626.          * name.
  2627.          */
  2628.  
  2629.     Forbid();
  2630.  
  2631.     if(!Directory[0])
  2632.     {
  2633.         if(!DirBuffer[0])
  2634.         {
  2635.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2636.  
  2637.             if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
  2638.                 LocalBuffer[0] = 0;
  2639.  
  2640.             if(!DirBuffer[0])
  2641.                 strcpy(DirBuffer,LocalBuffer);
  2642.         }
  2643.  
  2644.         Directory = DirBuffer;
  2645.     }
  2646.  
  2647.         /* If a wildcard pattern is required, add a gadget
  2648.          * to display it.
  2649.          */
  2650.  
  2651.     if(Pattern)
  2652.     {
  2653.         Flags = FILF_PATGAD;
  2654.  
  2655.         if(!Pattern[0])
  2656.         {
  2657.             DefaultPattern = TRUE;
  2658.  
  2659.             if(PatternBuffer[0])
  2660.                 Pattern = PatternBuffer;
  2661.             else
  2662.                 Pattern = "#?";
  2663.         }
  2664.         else
  2665.         {
  2666.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  2667.             {
  2668.                 DefaultPattern = TRUE;
  2669.  
  2670.                 Pattern = PatternBuffer;
  2671.             }
  2672.         }
  2673.     }
  2674.     else
  2675.     {
  2676.         Flags = 0;
  2677.  
  2678.         Pattern = "#?";
  2679.     }
  2680.  
  2681.     Permit();
  2682.  
  2683.         /* Set the save flag if we are about to save something. */
  2684.  
  2685.     if(SaveFlag)
  2686.         Flags |= FILF_SAVE;
  2687.  
  2688.         /* Set the multiselect bit if multiple files are
  2689.          * to be selected (e.g. for batch file upload).
  2690.          */
  2691.  
  2692.     if(MultiSelect)
  2693.         Flags |= FILF_MULTISELECT;
  2694.  
  2695.         /* Provide a standard `Ok' text if none
  2696.          * specified.
  2697.          */
  2698.  
  2699.     if(!OKText)
  2700.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  2701.  
  2702.         /* Allocate the asl.library directory requester
  2703.          * and display it.
  2704.          */
  2705.  
  2706.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2707.         ASL_Window,    Parent,
  2708.         ASL_File,    Name,
  2709.         ASL_Dir,    Directory,
  2710.         Title ? ASL_Hail : TAG_IGNORE,    Title,
  2711.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  2712.         ASL_Pattern,    Pattern,
  2713.         ASL_OKText,    OKText,
  2714.         ASL_ExtFlags1,    ExtFlags,
  2715.         ASLFR_TextAttr,    &UserFont,
  2716.         ASL_LeftEdge,    Left,
  2717.         ASL_TopEdge,    Top,
  2718.         ASL_Width,    Width,
  2719.         ASL_Height,    Height,
  2720.     TAG_DONE))
  2721.     {
  2722.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2723.         {
  2724.             PutWindowInfo(WINDOW_FILE,AslFileRequest -> rf_LeftEdge,AslFileRequest -> rf_TopEdge,AslFileRequest -> rf_Width,AslFileRequest -> rf_Height);
  2725.  
  2726.             if(!DirsOnly)
  2727.             {
  2728.                 STRPTR FileName;
  2729.  
  2730.                 if(AslFileRequest -> rf_NumArgs > 1 && AslFileRequest -> rf_ArgList)
  2731.                     FileName = AslFileRequest -> rf_ArgList -> wa_Name;
  2732.                 else
  2733.                     FileName = AslFileRequest -> rf_File;
  2734.  
  2735.                     /* Do we have a valid file name? */
  2736.  
  2737.                 if(FileName)
  2738.                 {
  2739.                         /* Build a legal path/file string. */
  2740.  
  2741.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2742.  
  2743.                     AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
  2744.  
  2745.                     Result = TRUE;
  2746.  
  2747.                     Forbid();
  2748.  
  2749.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2750.  
  2751.                     Permit();
  2752.                 }
  2753.             }
  2754.             else
  2755.             {
  2756.                 if(AslFileRequest -> rf_Dir[0])
  2757.                 {
  2758.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2759.  
  2760.                     Result = TRUE;
  2761.  
  2762.                     Forbid();
  2763.  
  2764.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2765.  
  2766.                     Permit();
  2767.                 }
  2768.             }
  2769.         }
  2770.     }
  2771.  
  2772.         /* We didn't get a file, no need to keep the
  2773.          * file requester.
  2774.          */
  2775.  
  2776.     if(!Result && AslFileRequest)
  2777.     {
  2778.         FreeAslRequest(AslFileRequest);
  2779.  
  2780.         return(NULL);
  2781.     }
  2782.     else
  2783.     {
  2784.         if(SaveFlag && AskWrite)
  2785.         {
  2786.             if(GetFileSize(Buffer))
  2787.             {
  2788.                 if(!MyEasyRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2789.                 {
  2790.                     FreeAslRequest(AslFileRequest);
  2791.  
  2792.                     return(NULL);
  2793.                 }
  2794.             }
  2795.         }
  2796.  
  2797.         Forbid();
  2798.  
  2799.         if(DefaultPattern)
  2800.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2801.  
  2802.         Permit();
  2803.  
  2804.         return(AslFileRequest);
  2805.     }
  2806. }
  2807.  
  2808.     /* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2809.      *
  2810.      *    Really quite simple varargs version of Intuition's
  2811.      *    EasyRequest requester.
  2812.      */
  2813.  
  2814. WORD __stdargs
  2815. MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2816. {
  2817.     struct EasyStruct    Easy;
  2818.     va_list            VarArgs;
  2819.     LONG            i,GadgetCount;
  2820.  
  2821.     for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
  2822.     {
  2823.         if(Gadgets[i] == '|')
  2824.             GadgetCount++;
  2825.     }
  2826.  
  2827.         /* Standard data. */
  2828.  
  2829.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2830.     Easy . es_Flags        = NULL;
  2831.     Easy . es_Title        = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2832.     Easy . es_TextFormat    = Text;
  2833.     Easy . es_GadgetFormat    = Gadgets;
  2834.  
  2835.     if(GadgetCount)
  2836.     {
  2837.         WORD Result;
  2838.  
  2839.         if(GTLayoutBase)
  2840.             LT_LockWindow(Window);
  2841.  
  2842.             /* Use the argument array to build the
  2843.              * requester and display it.
  2844.              */
  2845.  
  2846.         va_start(VarArgs,Gadgets);
  2847.         Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  2848.         va_end(VarArgs);
  2849.  
  2850.         if(GTLayoutBase)
  2851.             LT_UnlockWindow(Window);
  2852.  
  2853.         return(Result);
  2854.     }
  2855.     else
  2856.     {
  2857.         struct Window *ReqWindow;
  2858.  
  2859.         if(GTLayoutBase)
  2860.             LT_LockWindow(Window);
  2861.  
  2862.         va_start(VarArgs,Gadgets);
  2863.  
  2864.         if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,VarArgs))
  2865.         {
  2866.             ULONG    IDCMP;
  2867.             LONG    Result;
  2868.  
  2869.             FOREVER
  2870.             {
  2871.                 WaitPort(ReqWindow -> UserPort);
  2872.  
  2873.                 IDCMP = NULL;
  2874.  
  2875.                 Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
  2876.  
  2877.                 if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
  2878.                     break;
  2879.             }
  2880.  
  2881.             FreeSysRequest(ReqWindow);
  2882.         }
  2883.  
  2884.         va_end(VarArgs);
  2885.  
  2886.         if(GTLayoutBase)
  2887.             LT_UnlockWindow(Window);
  2888.  
  2889.         return(0);
  2890.     }
  2891. }
  2892.  
  2893.     /* CloseWindowSafely(struct Window *Window):
  2894.      *
  2895.      *    Close a window freeing all messages pending at
  2896.      *    its user port (taken from example source code
  2897.      *    published once upon a time in Amiga Mail).
  2898.      */
  2899.  
  2900. VOID __regargs
  2901. CloseWindowSafely(struct Window *Window)
  2902. {
  2903.     struct IntuiMessage    *IntuiMessage;
  2904.     struct Node        *Successor;
  2905.  
  2906.     Forbid();
  2907.  
  2908.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  2909.  
  2910.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  2911.     {
  2912.         if(IntuiMessage -> IDCMPWindow == Window)
  2913.         {
  2914.             Remove(IntuiMessage);
  2915.  
  2916.             ReplyMsg((struct Message *)IntuiMessage);
  2917.         }
  2918.  
  2919.         IntuiMessage = (struct IntuiMessage *)Successor;
  2920.     }
  2921.  
  2922.     Window -> UserPort = NULL;
  2923.  
  2924.     ModifyIDCMP(Window,NULL);
  2925.  
  2926.     Permit();
  2927.  
  2928.     LT_DeleteWindowLock(Window);
  2929.  
  2930.     CloseWindow(Window);
  2931. }
  2932.  
  2933.     /* WaitTime(LONG Secs,LONG Micros):
  2934.      *
  2935.      *    Wait a given period of time.
  2936.      */
  2937.  
  2938. VOID __regargs
  2939. WaitTime(LONG Secs,LONG Micros)
  2940. {
  2941.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2942.     TimeRequest -> tr_time . tv_secs    = Secs;
  2943.     TimeRequest -> tr_time . tv_micro    = Micros;
  2944.  
  2945.     DoIO(TimeRequest);
  2946. }
  2947.  
  2948.     /* StopTime():
  2949.      *
  2950.      *    Stop the running timer.
  2951.      */
  2952.  
  2953. VOID
  2954. StopTime()
  2955. {
  2956.     if(TimerRunning)
  2957.     {
  2958.         if(!CheckIO(TimeRequest))
  2959.             AbortIO(TimeRequest);
  2960.  
  2961.         WaitIO(TimeRequest);
  2962.     }
  2963. }
  2964.  
  2965.     /* StartTime(LONG Secs,LONG Micros):
  2966.      *
  2967.      *    Start the timer asynchronously.
  2968.      */
  2969.  
  2970. VOID __regargs
  2971. StartTime(LONG Secs,LONG Micros)
  2972. {
  2973.     StopTime();
  2974.  
  2975.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2976.     TimeRequest -> tr_time . tv_secs    = Secs;
  2977.     TimeRequest -> tr_time . tv_micro    = Micros;
  2978.  
  2979.     ClrSignal(SIG_TIMER);
  2980.  
  2981.     SendIO(TimeRequest);
  2982.  
  2983.     TimerRunning = TRUE;
  2984. }
  2985.  
  2986.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  2987.      *
  2988.      *    Get the contents of a vanilla AmigaDOS environment
  2989.      *    variable.
  2990.      */
  2991.  
  2992. STRPTR __regargs
  2993. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  2994. {
  2995.     LONG    Size;
  2996.     BPTR    File,SomeLock;
  2997.  
  2998.     Buffer[0] = 0;
  2999.  
  3000.         /* Is ENV: present? */
  3001.  
  3002.     if(SomeLock = Lock("Env:",ACCESS_READ))
  3003.     {
  3004.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  3005.  
  3006.         UnLock(SomeLock);
  3007.  
  3008.         strcpy(SomeBuffer,"Env:");
  3009.         strcat(SomeBuffer,Name);
  3010.  
  3011.             /* Open the file. */
  3012.  
  3013.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  3014.         {
  3015.                 /* Read the contents. */
  3016.  
  3017.             Size = Read(File,Buffer,256);
  3018.  
  3019.             Close(File);
  3020.  
  3021.             if(Size > 0)
  3022.             {
  3023.                 Buffer[Size] = 0;
  3024.  
  3025.                 return(Buffer);
  3026.             }
  3027.         }
  3028.     }
  3029.  
  3030.     return(NULL);
  3031. }
  3032.  
  3033.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  3034.      *
  3035.      *    Set the contents of a vanilla AmigaDOS environment
  3036.      *    variable.
  3037.      */
  3038.  
  3039. BYTE __regargs
  3040. SetEnvDOS(STRPTR Name,STRPTR Value)
  3041. {
  3042.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  3043.     LONG    Length;
  3044.     BPTR    File,FileLock;
  3045.     BYTE    Success = TRUE;
  3046.     WORD    i;
  3047.  
  3048.     for(i = 0 ; i < 2 ; i++)
  3049.     {
  3050.         if(i)
  3051.             Destination = "EnvArc:";
  3052.         else
  3053.             Destination = "Env:";
  3054.  
  3055.             /* Is ENV:/ENVARC: present? */
  3056.  
  3057.         if(FileLock = Lock(Destination,ACCESS_READ))
  3058.         {
  3059.             UnLock(FileLock);
  3060.  
  3061.             strcpy(Buffer,Destination);
  3062.             strcat(Buffer,Name);
  3063.  
  3064.                 /* There already is a variable of that
  3065.                  * name in the environment storage
  3066.                  * directory.
  3067.                  */
  3068.  
  3069.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  3070.             {
  3071.                 UnLock(FileLock);
  3072.  
  3073.                     /* Delete the variable. */
  3074.  
  3075.                 if(!DeleteFile(Buffer))
  3076.                 {
  3077.                     Success = FALSE;
  3078.  
  3079.                     continue;
  3080.                 }
  3081.             }
  3082.  
  3083.                 /* Set the new variable. */
  3084.  
  3085.             if(Length = strlen(Value))
  3086.             {
  3087.                 if(File = Open(Buffer,MODE_NEWFILE))
  3088.                 {
  3089.                     if(Write(File,Value,Length) != Length)
  3090.                     {
  3091.                         Close(File);
  3092.  
  3093.                         DeleteFile(Buffer);
  3094.  
  3095.                         Success = FALSE;
  3096.                     }
  3097.                     else
  3098.                     {
  3099.                         Close(File);
  3100.  
  3101.                         AddProtection(Buffer,FIBF_EXECUTE);
  3102.                     }
  3103.                 }
  3104.                 else
  3105.                     Success = FALSE;
  3106.             }
  3107.         }
  3108.         else
  3109.             Success = FALSE;
  3110.     }
  3111.  
  3112.     return(Success);
  3113. }
  3114.  
  3115.     /* BumpWindow(struct Window *SomeWindow):
  3116.      *
  3117.      *    Bring a window to the front (and shift the screen
  3118.      *    back to its initial position).
  3119.      */
  3120.  
  3121. VOID __regargs
  3122. BumpWindow(struct Window *SomeWindow)
  3123. {
  3124.     if(SomeWindow)
  3125.     {
  3126.         if(SomeWindow -> WScreen -> LeftEdge > 0)
  3127.         {
  3128.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3129.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  3130.             else
  3131.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  3132.         }
  3133.         else
  3134.         {
  3135.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3136.                 MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  3137.         }
  3138.  
  3139.         ScreenToFront(SomeWindow -> WScreen);
  3140.  
  3141.         ActivateWindow(SomeWindow);
  3142.     }
  3143. }
  3144.  
  3145.     /* PushWindow(struct Window *Window):
  3146.      *
  3147.      *    Push/PopWindow implement a single lifo window stack
  3148.      *    which always updates the window to activate when
  3149.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  3150.      *    push a window on the stack.
  3151.      */
  3152.  
  3153. VOID __regargs
  3154. PushWindow(struct Window *Window)
  3155. {
  3156.     if(WindowStackPtr < 5)
  3157.     {
  3158.         WindowStack[WindowStackPtr++] = Window;
  3159.  
  3160.         TopWindow = Window;
  3161.     }
  3162. }
  3163.  
  3164.     /* PopWindow():
  3165.      *
  3166.      *    Remove topmost window from window stack.
  3167.      */
  3168.  
  3169. VOID
  3170. PopWindow()
  3171. {
  3172.     if(WindowStackPtr > 0)
  3173.     {
  3174.         WindowStackPtr--;
  3175.  
  3176.         if(WindowStackPtr)
  3177.             TopWindow = WindowStack[WindowStackPtr - 1];
  3178.         else
  3179.             TopWindow = Window;
  3180.     }
  3181. }
  3182.  
  3183.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  3184.      *
  3185.      *    Load the keyboard macros from a file.
  3186.      */
  3187.  
  3188. BYTE __regargs
  3189. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  3190. {
  3191.     struct IFFHandle    *Handle;
  3192.     BYTE             Success = FALSE;
  3193.     struct StoredProperty    *Prop;
  3194.     struct TermInfo        *TermInfo;
  3195.     LONG             Error;
  3196.  
  3197.     if(Handle = AllocIFF())
  3198.     {
  3199.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3200.         {
  3201.             InitIFFasDOS(Handle);
  3202.  
  3203.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3204.             {
  3205.                 /* Collect version number ID if
  3206.                  * available.
  3207.                  */
  3208.  
  3209.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3210.                 {
  3211.                     /* The following line tells iffparse to stop at the
  3212.                      * very beginning of a `Type' chunk contained in a
  3213.                      * `TERM' FORM chunk.
  3214.                      */
  3215.  
  3216.                     if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
  3217.                     {
  3218.                         /* Parse the file... */
  3219.  
  3220.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3221.                         {
  3222.                             /* Did we get a version ID? */
  3223.  
  3224.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3225.                             {
  3226.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3227.  
  3228.                                 /* Is it the file format we are able
  3229.                                  * to read?
  3230.                                  */
  3231.  
  3232.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3233.                                 {
  3234.                                         /* Probably an older revision. */
  3235.  
  3236.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  3237.                                     {
  3238.                                         memset(Keys,0,sizeof(struct MacroKeys));
  3239.  
  3240.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3241.                                             Success = TRUE;
  3242.                                         else
  3243.                                             Error = IoErr();
  3244.                                     }
  3245.                                     else
  3246.                                         Error = ERR_OUTDATED;
  3247.                                 }
  3248.                                 else
  3249.                                 {
  3250.                                     /* The file read pointer is positioned
  3251.                                      * just in front of the first data
  3252.                                      * to be read, so let's don't disappoint
  3253.                                      * iffparse and read it.
  3254.                                      */
  3255.  
  3256.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  3257.                                         Success = TRUE;
  3258.                                     else
  3259.                                         Error = IoErr();
  3260.                                 }
  3261.                             }
  3262.                             else
  3263.                             {
  3264.                                     /* File was created by WriteIFFData previous
  3265.                                      * to revision 1.4.
  3266.                                      */
  3267.  
  3268.                                 memset(Keys,0,sizeof(struct MacroKeys));
  3269.  
  3270.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3271.                                     Success = TRUE;
  3272.                                 else
  3273.                                     Error = IoErr();
  3274.                             }
  3275.                         }
  3276.                     }
  3277.                 }
  3278.  
  3279.                 CloseIFF(Handle);
  3280.             }
  3281.  
  3282.             Close(Handle -> iff_Stream);
  3283.         }
  3284.         else
  3285.             Error = IoErr();
  3286.  
  3287.         FreeIFF(Handle);
  3288.     }
  3289.     else
  3290.         Error = ERR_NO_MEM;
  3291.  
  3292.     if(Error)
  3293.         SetIoErr(Error);
  3294.  
  3295.     return(Success);
  3296. }
  3297.  
  3298.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3299.      *
  3300.      *    Write data to an IFF file (via iffparse.library).
  3301.      */
  3302.  
  3303. BYTE __regargs
  3304. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3305. {
  3306.     struct IFFHandle    *Handle;
  3307.     BYTE             Success = FALSE;
  3308.     LONG             Error;
  3309.  
  3310.         /* Allocate a handle. */
  3311.  
  3312.     if(Handle = AllocIFF())
  3313.     {
  3314.             /* Open an output stream. */
  3315.  
  3316.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  3317.         {
  3318.                 /* Tell iffparse that this is
  3319.                  * a DOS handle.
  3320.                  */
  3321.  
  3322.             InitIFFasDOS(Handle);
  3323.  
  3324.                 /* Open the handle for writing. */
  3325.  
  3326.             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  3327.             {
  3328.                     /* Push outmost chunk onto stack. */
  3329.  
  3330.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  3331.                 {
  3332.                         /* Add a version identifier. */
  3333.  
  3334.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  3335.                     {
  3336.                         struct TermInfo TermInfo;
  3337.  
  3338.                         TermInfo . Version    = CONFIG_FILE_VERSION;
  3339.                         TermInfo . Revision    = CONFIG_FILE_REVISION;
  3340.  
  3341.                             /* Write the version data. */
  3342.  
  3343.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3344.                         {
  3345.                                 /* Pop the version chunk, i.e. write it to the file. */
  3346.  
  3347.                             if(Error = PopChunk(Handle))
  3348.                                 Success = FALSE;
  3349.                             else
  3350.                             {
  3351.                                     /* Push the real data chunk on the stack. */
  3352.  
  3353.                                 if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
  3354.                                 {
  3355.                                         /* Write the data. */
  3356.  
  3357.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3358.                                         Success = TRUE;
  3359.                                     else
  3360.                                         Error = IoErr();
  3361.  
  3362.                                             /* Pop the data chunk. */
  3363.  
  3364.                                     if(Success)
  3365.                                     {
  3366.                                         if(Error = PopChunk(Handle))
  3367.                                             Success = FALSE;
  3368.                                     }
  3369.                                 }
  3370.                                 else
  3371.                                     Success = FALSE;
  3372.                             }
  3373.                         }
  3374.                         else
  3375.                         {
  3376.                             Error = IoErr();
  3377.  
  3378.                             Success = FALSE;
  3379.                         }
  3380.                     }
  3381.  
  3382.                         /* Seems that we're done, now try to pop the FORM chunk
  3383.                          * and return.
  3384.                          */
  3385.  
  3386.                     if(Success)
  3387.                     {
  3388.                         if(Error = PopChunk(Handle))
  3389.                             Success = FALSE;
  3390.                     }
  3391.                 }
  3392.  
  3393.                     /* Close the handle (flush any pending data). */
  3394.  
  3395.                 CloseIFF(Handle);
  3396.             }
  3397.  
  3398.                 /* Close the DOS handle itself. */
  3399.  
  3400.             Close(Handle -> iff_Stream);
  3401.         }
  3402.         else
  3403.             Error = IoErr();
  3404.  
  3405.             /* And free the IFF handle. */
  3406.  
  3407.         FreeIFF(Handle);
  3408.     }
  3409.     else
  3410.         Error = ERR_NO_MEM;
  3411.  
  3412.     if(Success)
  3413.         AddProtection(Name,FIBF_EXECUTE);
  3414.  
  3415.     if(Error)
  3416.         SetIoErr(Error);
  3417.  
  3418.     return(Success);
  3419. }
  3420.  
  3421.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3422.      *
  3423.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3424.      */
  3425.  
  3426. BYTE __regargs
  3427. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3428. {
  3429.     struct IFFHandle    *Handle;
  3430.     BYTE             Success = FALSE;
  3431.     struct StoredProperty    *Prop;
  3432.     struct TermInfo        *TermInfo;
  3433.     LONG             Error = 0;
  3434.  
  3435.     if(Handle = AllocIFF())
  3436.     {
  3437.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3438.         {
  3439.             InitIFFasDOS(Handle);
  3440.  
  3441.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3442.             {
  3443.                 /* Collect version number ID if
  3444.                  * available.
  3445.                  */
  3446.  
  3447.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3448.                 {
  3449.                     /* The following line tells iffparse to stop at the
  3450.                      * very beginning of a `Type' chunk contained in a
  3451.                      * `TERM' FORM chunk.
  3452.                      */
  3453.  
  3454.                     if(!(Error = StopChunk(Handle,ID_TERM,Type)))
  3455.                     {
  3456.                         /* Parse the file... */
  3457.  
  3458.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3459.                         {
  3460.                             /* Did we get a version ID? */
  3461.  
  3462.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3463.                             {
  3464.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3465.  
  3466.                                 /* Is it the file format we are able
  3467.                                  * to read?
  3468.                                  */
  3469.  
  3470.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3471.                                 {
  3472.                                     Error = ERR_OUTDATED;
  3473.  
  3474.                                     Success = FALSE;
  3475.                                 }
  3476.                                 else
  3477.                                 {
  3478.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3479.  
  3480.                                     if(Chunk -> cn_Size < Size)
  3481.                                         Size = Chunk -> cn_Size;
  3482.  
  3483.                                     /* The file read pointer is positioned
  3484.                                      * just in front of the first data
  3485.                                      * to be read, so let's don't disappoint
  3486.                                      * iffparse and read it.
  3487.                                      */
  3488.  
  3489.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3490.                                         Success = TRUE;
  3491.                                     else
  3492.                                         Error = IoErr();
  3493.                                 }
  3494.                             }
  3495.                         }
  3496.                     }
  3497.                 }
  3498.  
  3499.                 CloseIFF(Handle);
  3500.             }
  3501.  
  3502.             Close(Handle -> iff_Stream);
  3503.         }
  3504.         else
  3505.             Error = IoErr();
  3506.  
  3507.         FreeIFF(Handle);
  3508.     }
  3509.  
  3510.     if(Error)
  3511.         SetIoErr(Error);
  3512.  
  3513.     return(Success);
  3514. }
  3515.  
  3516.     /* SplitFileName():
  3517.      *
  3518.      *    Split a full file name into a file and a drawer name.
  3519.      */
  3520.  
  3521. VOID __regargs
  3522. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  3523. {
  3524.     if(FilePart(FullName) == FullName)
  3525.     {
  3526.         *DrawerName    = 0;
  3527.         *FileName    = FullName;
  3528.     }
  3529.     else
  3530.     {
  3531.         STRPTR Dummy;
  3532.  
  3533.         strcpy(DrawerName,FullName);
  3534.  
  3535.         Dummy = PathPart(DrawerName);
  3536.  
  3537.         *Dummy = 0;
  3538.  
  3539.         *FileName = FilePart(FullName);
  3540.     }
  3541. }
  3542.  
  3543.     /* CreateList():
  3544.      *
  3545.      *    Create a small, empty list.
  3546.      */
  3547.  
  3548. struct List *
  3549. CreateList()
  3550. {
  3551.     struct List *List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY);
  3552.  
  3553.     if(List)
  3554.         NewList(List);
  3555.  
  3556.     return(List);
  3557. }
  3558.  
  3559.     /* DeleteList():
  3560.      *
  3561.      *    Free the contents of a list and the list itself.
  3562.      */
  3563.  
  3564. VOID __regargs
  3565. DeleteList(struct List *List)
  3566. {
  3567.     if(List)
  3568.     {
  3569.         struct Node    *Node,
  3570.                 *Next;
  3571.  
  3572.         for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3573.             FreeVecPooled(Node);
  3574.  
  3575.         FreeVecPooled(List);
  3576.     }
  3577. }
  3578.  
  3579.     /* BackfillRoutine():
  3580.      *
  3581.      *    Window layer backfill routine.
  3582.      */
  3583.  
  3584. ULONG __asm __saveds
  3585. BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort)
  3586. {
  3587.     struct RastPort RastPort = *RPort;
  3588.  
  3589.     RPort = &RastPort;
  3590.  
  3591.     RPort -> Layer = NULL;
  3592.  
  3593.     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  3594.     SetDrMd(RPort,JAM1);
  3595.  
  3596.     RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY);
  3597.  
  3598.     return(TRUE);
  3599. }
  3600.  
  3601. struct NameSegment
  3602. {
  3603.     UBYTE    String[63],
  3604.         Separator;
  3605. };
  3606.  
  3607. STATIC UBYTE * __regargs
  3608. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,WORD i)
  3609. {
  3610.     UBYTE *xp = NameSegment[i] . String;
  3611.  
  3612.     while (*cp && !strchr("._+-,@~=",*cp))
  3613.         *xp++ = *cp++;
  3614.  
  3615.     *xp = '\0';
  3616.  
  3617.     NameSegment[i] . Separator = *cp;
  3618.  
  3619.     if (*cp)
  3620.         cp++;
  3621.  
  3622.     if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
  3623.         return(cp);
  3624.     else
  3625.         return(NULL);
  3626. }
  3627.  
  3628. STATIC VOID __regargs
  3629. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,WORD Zap)
  3630. {
  3631.     UBYTE *cp = Destination,*xp;
  3632.  
  3633.     for(xp = NameSegment[0] . String ; *xp ; )
  3634.         *cp++ = *xp++;
  3635.  
  3636.     if(NameSegment[0] . Separator)
  3637.     {
  3638.         register WORD i;
  3639.  
  3640.         *cp++ = NameSegment[0] . Separator;
  3641.  
  3642.         for(i = Zap + 1 ; ; i++)
  3643.         {
  3644.             for(xp = NameSegment[i] . String ; *xp ; )
  3645.                 *cp++ = *xp++;
  3646.  
  3647.             if(NameSegment[i] . Separator)
  3648.                 *cp++ = NameSegment[i] . Separator;
  3649.             else
  3650.             {
  3651.                 if(!NameSegment[i] . String[0])
  3652.                     break;
  3653.             }
  3654.         }
  3655.     }
  3656.  
  3657.     *cp = 0;
  3658. }
  3659.  
  3660.     /* ShrinkName():
  3661.      *
  3662.      *    Shrink a file name down to a number of characters, if
  3663.      *    possible preserving the structure of the name. Algorithm
  3664.      *    courtesy of the "shrink" program by Simon Brown,
  3665.      *    Edinburgh University.
  3666.      */
  3667.  
  3668. UBYTE * __regargs
  3669. ShrinkName(const UBYTE *Source,UBYTE *Destination,WORD MaxLength,BOOLEAN FixSuffix)
  3670. {
  3671.     #define MAXSEGS 10
  3672.  
  3673.     struct NameSegment NameSegment[MAXSEGS];
  3674.  
  3675.     WORD i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  3676.     UBYTE *OldPtr = (UBYTE *)Source;
  3677.  
  3678.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  3679.  
  3680.     if(i < MAXSEGS)
  3681.     {
  3682.         NumSegments = i - 1;
  3683.  
  3684.         if((NumSegments * 2) < MaxLength)
  3685.         {
  3686.             SuffixLength = strlen(NameSegment[NumSegments] . String);
  3687.  
  3688.             if(SuffixLength > MaxLength - NumSegments - 1)
  3689.             {
  3690.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  3691.  
  3692.                 NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
  3693.             }
  3694.             else
  3695.             {
  3696.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  3697.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  3698.             }
  3699.  
  3700.             if(NumSegments >= 1)
  3701.             {
  3702.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  3703.                 {
  3704.                     if(NameSegment[i] . Separator)
  3705.                         SuffixLength++;
  3706.                 }
  3707.  
  3708.                 if(NameSegment[0] . Separator)
  3709.                     SuffixLength++;
  3710.  
  3711.                 Remainder = MaxLength - SuffixLength;
  3712.  
  3713.                 Delete = Remainder / NumSegments;
  3714.  
  3715.                 Total = SuffixLength;
  3716.  
  3717.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  3718.                 {
  3719.                     NameSegment[i] . String[Delete] = 0;
  3720.  
  3721.                     Total += Delete;
  3722.                 }
  3723.  
  3724.                 NameSegment[0] . String[MaxLength - Total] = 0;
  3725.             }
  3726.  
  3727.             CopyNameSegment(NameSegment,Destination,Zap);
  3728.         }
  3729.         else
  3730.             strcpy(Destination,Source);
  3731.     }
  3732.     else
  3733.         strcpy(Destination,Source);
  3734.  
  3735.     if(FixSuffix)
  3736.     {
  3737.         BOOLEAN    GotDot    = FALSE;
  3738.         LONG    Len    = strlen(Destination),Dots;
  3739.  
  3740.         for(i = Dots = 0 ; i < Len ; i++)
  3741.         {
  3742.             if(Destination[i] == '.')
  3743.                 Dots++;
  3744.         }
  3745.  
  3746.         if(!Dots)
  3747.         {
  3748.             if(Len < 4)
  3749.                 strcat(Destination,".___");
  3750.             else
  3751.                 Destination[Len - 4] = '.';
  3752.         }
  3753.  
  3754.         for(i = Len - 1 ; i >= 0 ; i--)
  3755.         {
  3756.             if(Destination[i] == '.')
  3757.             {
  3758.                 if(GotDot)
  3759.                     Destination[i] = '_';
  3760.                 else
  3761.                     GotDot = TRUE;
  3762.             }
  3763.  
  3764.             if(Destination[i] == '\\')
  3765.                 Destination[i] = '-';
  3766.         }
  3767.     }
  3768.  
  3769.     return(Destination);
  3770. }
  3771.  
  3772.     /* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
  3773.      *
  3774.      *    Build a font name and size string from given
  3775.      *    information (raw name and size).
  3776.      */
  3777.  
  3778. VOID __regargs
  3779. BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
  3780. {
  3781.     UBYTE    LocalBuffer[50];
  3782.     LONG    Len;
  3783.  
  3784.     strcpy(LocalBuffer,FilePart((STRPTR)Name));
  3785.  
  3786.     Len = strlen(LocalBuffer);
  3787.  
  3788.     if(Len > 5)
  3789.     {
  3790.         if(!Stricmp(&LocalBuffer[Len - 5],".font"))
  3791.             LocalBuffer[Len - 5] = 0;
  3792.     }
  3793.  
  3794.     SPrintf(Destination,"%s %ld",LocalBuffer,Size);
  3795. }
  3796.  
  3797.     /* CreateMenuGlyphs():
  3798.      *
  3799.      *    Create scaled glyphs for pull-down menus.
  3800.      */
  3801.  
  3802. BOOLEAN __regargs
  3803. CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
  3804. {
  3805.     struct Image    *AmigaGlyph,
  3806.             *CheckGlyph;
  3807.     LONG         AspectX,AspectY,
  3808.              Size,FontHeight;
  3809.  
  3810.     FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
  3811.  
  3812.     if(Screen -> Flags & SCREENHIRES)
  3813.         Size = SYSISIZE_MEDRES;
  3814.     else
  3815.         Size = SYSISIZE_LOWRES;
  3816.  
  3817.     AspectX = DrawInfo -> dri_Resolution . X;
  3818.     AspectY = DrawInfo -> dri_Resolution . Y;
  3819.  
  3820.     if(AmigaGlyph = NewObject(NULL,SYSICLASS,
  3821.         SYSIA_DrawInfo,    DrawInfo,
  3822.         SYSIA_Size,    Size,
  3823.         SYSIA_Which,    AMIGAKEY,
  3824.         IA_Left,    0,
  3825.         LA_Top,        0,
  3826.         IA_Width,    (FontHeight * 3 * AspectY) / (2 * AspectX),
  3827.         IA_Height,    FontHeight,
  3828.     TAG_DONE))
  3829.     {
  3830.         if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
  3831.             SYSIA_DrawInfo,    DrawInfo,
  3832.             SYSIA_Size,    Size,
  3833.             SYSIA_Which,    MENUCHECK,
  3834.             IA_Left,    0,
  3835.             LA_Top,        0,
  3836.             IA_Width,    (FontHeight * AspectY) / AspectX,
  3837.             IA_Height,    FontHeight,
  3838.         TAG_DONE)))
  3839.         {
  3840.             DisposeObject(AmigaGlyph);
  3841.  
  3842.             AmigaGlyph = NULL;
  3843.         }
  3844.     }
  3845.  
  3846.     if(AmigaGlyph && CheckGlyph)
  3847.     {
  3848.         *AmigaPtr = AmigaGlyph;
  3849.         *CheckPtr = CheckGlyph;
  3850.  
  3851.         return(TRUE);
  3852.     }
  3853.     else
  3854.         return(FALSE);
  3855. }
  3856.  
  3857.     /* FixName(STRPTR Name):
  3858.      *
  3859.      *    Build a correct AmigaDOS filename.
  3860.      */
  3861.  
  3862. VOID __regargs
  3863. FixName(STRPTR Name)
  3864. {
  3865.     WORD    NameLen    = strlen(Name),
  3866.         i;
  3867.  
  3868.         /* Replace special characters. */
  3869.  
  3870.     for(i = 0 ; i < NameLen ; i++)
  3871.     {
  3872.         switch(Name[i])
  3873.         {
  3874.             case ' ':
  3875.  
  3876.                 Name[i] = '_';
  3877.                 break;
  3878.  
  3879.             case ':':
  3880.  
  3881.                 Name[i] = '.';
  3882.                 break;
  3883.  
  3884.             case '/':
  3885.  
  3886.                 Name[i] = '\\';
  3887.                 break;
  3888.  
  3889.             case '\"':
  3890.  
  3891.                 Name[i] = '\'';
  3892.                 break;
  3893.         }
  3894.     }
  3895.  
  3896.         /* Truncate the name. */
  3897.  
  3898.     if(NameLen > 31)
  3899.         Name[31] = 0;
  3900. }
  3901.  
  3902.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  3903.      *
  3904.      *    Display an error message, in human readable form if possible.
  3905.      */
  3906.  
  3907. VOID __regargs
  3908. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  3909. {
  3910.     STATIC LONG LocalErrors[][2] =
  3911.     {
  3912.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  3913.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  3914.         ERR_NO_MEM,            MSG_ERR_NO_MEM_TXT,
  3915.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  3916.         ERR_EXECUTE_ERROR,        MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT,
  3917.  
  3918.         ERR_FILE_NOT_FOUND,        MSG_VERIFY_NO_FILE_TXT,
  3919.         ERR_DRAWER_NOT_FOUND,        MSG_VERIFY_DRAWER_NOT_FOUND_TXT,
  3920.         ERR_PROGRAM_NOT_FOUND,        MSG_VERIFY_NO_PROGRAM_TXT,
  3921.         ERR_NOT_A_FILE,            MSG_VERIFY_DRAWER_NOT_A_FILE_TXT,
  3922.         ERR_NOT_A_DRAWER,        MSG_VERIFY_FILE_NOT_A_DRAWER_TXT,
  3923.  
  3924.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  3925.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  3926.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  3927.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  3928.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  3929.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  3930.  
  3931.         0,                0
  3932.     };
  3933.  
  3934.     STRPTR    PrimaryError    = NULL,
  3935.         SecondaryError    = NULL;
  3936.  
  3937.     if(Primary)
  3938.     {
  3939.         LONG i;
  3940.  
  3941.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3942.         {
  3943.             if(LocalErrors[i][0] == Primary)
  3944.             {
  3945.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  3946.  
  3947.                 break;
  3948.             }
  3949.         }
  3950.  
  3951.         if(!PrimaryError)
  3952.         {
  3953.             STATIC UBYTE __far Buffer[256];
  3954.  
  3955.             Fault(Primary,"",Buffer,256);
  3956.  
  3957.             PrimaryError = Buffer + 2;
  3958.         }
  3959.     }
  3960.  
  3961.     if(Secondary)
  3962.     {
  3963.         LONG i;
  3964.  
  3965.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3966.         {
  3967.             if(LocalErrors[i][0] == Secondary)
  3968.             {
  3969.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  3970.  
  3971.                 break;
  3972.             }
  3973.         }
  3974.  
  3975.         if(!SecondaryError)
  3976.         {
  3977.             STATIC UBYTE __far Buffer[256];
  3978.  
  3979.             Fault(Secondary,"",Buffer,256);
  3980.  
  3981.             SecondaryError = Buffer + 2;
  3982.         }
  3983.     }
  3984.  
  3985.     if(PrimaryError)
  3986.     {
  3987.         if(String)
  3988.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  3989.         else
  3990.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  3991.     }
  3992. }
  3993.  
  3994. struct RendezvousData * __saveds __asm
  3995. RendezvousLogin(register __a0 struct MsgPort *ReadPort,register __a1 struct MsgPort *WritePort,register __a2 struct TagItem *TagList)
  3996. {
  3997.     struct RendezvousData *Data;
  3998.  
  3999.     if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
  4000.     {
  4001.         struct DataMsg Msg;
  4002.  
  4003.         InitMsgItem(&Msg,TaskDestructor);
  4004.  
  4005.         Msg . Type = DATAMSGTYPE_RENDEZVOUS;
  4006.         Msg . Data = (UBYTE *)SysBase -> ThisTask;
  4007.  
  4008.         Forbid();
  4009.  
  4010.         ClrSignal(SIGBREAKF_CTRL_F);
  4011.  
  4012.         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  4013.  
  4014.         Wait(SIGBREAKF_CTRL_F);
  4015.  
  4016.         Permit();
  4017.  
  4018.         if(ReadRequest && WriteRequest)
  4019.         {
  4020.             struct List *UploadList;
  4021.  
  4022.             CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
  4023.  
  4024.             Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
  4025.  
  4026.             CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
  4027.  
  4028.             Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
  4029.  
  4030.             if(Window)
  4031.                 Data -> rd_Screen = Window -> WScreen;
  4032.  
  4033.             NewList(&Data -> rd_UploadList);
  4034.             NewList(&Data -> rd_DownloadList);
  4035.             NewList(&Data -> rd_SentList);
  4036.             NewList(&Data -> rd_ReceivedList);
  4037.  
  4038.             if(UploadList = GetUploadList())
  4039.             {
  4040.                 struct Node *Node,*Next;
  4041.  
  4042.                 for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4043.                     AddTail(&Data -> rd_UploadList,Node);
  4044.  
  4045.                 FreeVecPooled(UploadList);
  4046.             }
  4047.  
  4048.             Data -> rd_SendPath    = Config -> PathConfig -> BinaryUploadPath;
  4049.             Data -> rd_ReceivePath    = Config -> PathConfig -> BinaryDownloadPath;
  4050.             Data -> rd_Options    = "";
  4051.         }
  4052.         else
  4053.         {
  4054.             FreeVecPooled(Data);
  4055.  
  4056.             Data = NULL;
  4057.         }
  4058.     }
  4059.  
  4060.     return(Data);
  4061. }
  4062.  
  4063. VOID __saveds __asm
  4064. RendezvousLogoff(register __a0 struct RendezvousData *Data)
  4065. {
  4066.     if(Data)
  4067.     {
  4068.         struct Node *Node,*Next;
  4069.  
  4070.         for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4071.             FreeVecPooled(Node);
  4072.  
  4073.         for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4074.             FreeVecPooled(Node);
  4075.  
  4076.         for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4077.             FreeVecPooled(Node);
  4078.  
  4079.         for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4080.             FreeVecPooled(Node);
  4081.  
  4082.         FreeVecPooled(Data);
  4083.  
  4084.         Signal(ThisProcess,SIG_HANDSHAKE);
  4085.     }
  4086. }
  4087.  
  4088. struct Node * __saveds __asm
  4089. RendezvousNewNode(register __a0 STRPTR Name)
  4090. {
  4091.     if(Name)
  4092.     {
  4093.         LONG Len;
  4094.  
  4095.         if(Len = strlen(Name))
  4096.         {
  4097.             struct Node *Node;
  4098.  
  4099.             if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  4100.             {
  4101.                 memset(Node,0,sizeof(struct Node));
  4102.  
  4103.                 strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
  4104.  
  4105.                 return(Node);
  4106.             }
  4107.         }
  4108.     }
  4109.  
  4110.     return(NULL);
  4111. }
  4112.  
  4113. struct List * __regargs
  4114. BuildModeList(LONG *Index,ULONG DisplayMode,ULONG (* __asm ModeFilter)(register __a1 ULONG ID))
  4115. {
  4116.     struct List    *List;
  4117.     LONG         Count = 0;
  4118.  
  4119.     *Index = 0;
  4120.  
  4121.     if(List = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  4122.     {
  4123.         struct DisplayInfo    DisplayInfo;
  4124.         ULONG            SomeMode = INVALID_ID;
  4125.  
  4126.         NewList(List);
  4127.  
  4128.         while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
  4129.         {
  4130.             if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
  4131.             {
  4132.                 if((DisplayInfo . PropertyFlags & DIPF_IS_WB) && !DisplayInfo . NotAvailable)
  4133.                 {
  4134.                     STRPTR Name;
  4135.  
  4136.                     if(ModeFilter)
  4137.                     {
  4138.                         if(!(*ModeFilter)(SomeMode))
  4139.                             continue;
  4140.                     }
  4141.  
  4142.                     if(Name = GetModeName(SomeMode))
  4143.                     {
  4144.                         struct ModeNode    *ModeNode;
  4145.  
  4146.                         if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(Name) + 1,MEMF_ANY))
  4147.                         {
  4148.                             ModeNode -> VanillaNode . ln_Name = (STRPTR)(ModeNode + 1);
  4149.  
  4150.                             strcpy(ModeNode -> VanillaNode . ln_Name,Name);
  4151.  
  4152.                             ModeNode -> DisplayID = SomeMode;
  4153.  
  4154.                             AddTail(List,ModeNode);
  4155.  
  4156.                             Count++;
  4157.                         }
  4158.                     }
  4159.                 }
  4160.             }
  4161.         }
  4162.     }
  4163.  
  4164.     if(Count)
  4165.     {
  4166.         struct ModeNode    *Node,
  4167.                 *Next;
  4168.  
  4169.         for(Node = (struct ModeNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct ModeNode *)Node -> VanillaNode . ln_Succ)
  4170.         {
  4171.             if(!(Node -> DisplayID & MONITOR_ID_MASK))
  4172.             {
  4173.                 for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4174.                 {
  4175.                     if((Node -> DisplayID & ~MONITOR_ID_MASK) == (Next -> DisplayID & ~MONITOR_ID_MASK) && Next != Node)
  4176.                         Node -> DisplayID = INVALID_ID;
  4177.                 }
  4178.             }
  4179.  
  4180.             for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4181.             {
  4182.                 if(Node -> DisplayID == Next -> DisplayID && Next != Node)
  4183.                     Next -> DisplayID = INVALID_ID;
  4184.             }
  4185.         }
  4186.  
  4187.         for(Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4188.         {
  4189.             if(Node -> DisplayID == INVALID_ID)
  4190.             {
  4191.                 Count--;
  4192.  
  4193.                 Remove(Node);
  4194.  
  4195.                 FreeVecPooled(Node);
  4196.             }
  4197.         }
  4198.     }
  4199.  
  4200.     if(Count)
  4201.     {
  4202.         struct ModeNode    *Node,
  4203.                 *Next;
  4204.  
  4205.         for(Count = 0, Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4206.         {
  4207.             if(Node -> DisplayID == DisplayMode)
  4208.             {
  4209.                 *Index = Count;
  4210.  
  4211.                 break;
  4212.             }
  4213.         }
  4214.  
  4215.         return(List);
  4216.     }
  4217.     else
  4218.     {
  4219.         DeleteList(List);
  4220.  
  4221.         return(NULL);
  4222.     }
  4223. }
  4224.  
  4225.     /* IsAssign(STRPTR Name):
  4226.      *
  4227.      *    Does a name refer to an assignment?
  4228.      */
  4229.  
  4230. BOOLEAN __regargs
  4231. IsAssign(STRPTR Name)
  4232. {
  4233.     WORD NameLen    = strlen(Name) - 1;
  4234.     BOOLEAN Result    = FALSE;
  4235.  
  4236.         /* Does it end with a colon? */
  4237.  
  4238.     if(Name[NameLen] == ':')
  4239.     {
  4240.         struct DosList *DosList;
  4241.  
  4242.             /* Lock the list of assignments for reading. */
  4243.  
  4244.         DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ);
  4245.  
  4246.             /* Make sure the v37 bug doesn't catch us. */
  4247.  
  4248.         if(((ULONG)DosList) > 1)
  4249.         {
  4250.             STRPTR AssignName;
  4251.  
  4252.                 /* Scan the list... */
  4253.  
  4254.             while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  4255.             {
  4256.                     /* Convert the name from icky
  4257.                      * BCPL to `C' style string.
  4258.                      */
  4259.  
  4260.                 AssignName = (STRPTR)BADDR(DosList -> dol_Name);
  4261.  
  4262.                     /* Does the name length match? */
  4263.  
  4264.                 if(AssignName[0] == NameLen)
  4265.                 {
  4266.                         /* Does the name itself match? */
  4267.  
  4268.                     if(!Strnicmp(&AssignName[1],Name,NameLen))
  4269.                     {
  4270.                         Result = TRUE;
  4271.  
  4272.                         break;
  4273.                     }
  4274.                 }
  4275.             }
  4276.  
  4277.                 /* Unlock the list of assignments. */
  4278.  
  4279.             UnLockDosList(LDF_ASSIGNS | LDF_READ);
  4280.         }
  4281.     }
  4282.  
  4283.         /* Return the result. */
  4284.  
  4285.     return(Result);
  4286. }
  4287.  
  4288.     /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
  4289.      *
  4290.      *    Check if a file lock is part of an assignment.
  4291.      */
  4292.  
  4293. BOOLEAN __regargs
  4294. LockInAssign(BPTR TheLock,STRPTR TheAssignment)
  4295. {
  4296.     struct DevProc    *DevProc    = NULL;
  4297.     struct MsgPort    *FileSysTask    = GetFileSysTask();
  4298.     BOOLEAN         Result        = FALSE;
  4299.  
  4300.  
  4301.         /* Loop until all assignments are
  4302.          * processed.
  4303.          */
  4304.  
  4305.     do
  4306.     {
  4307.             /* Get the default filesystem task
  4308.              * in case we stumble upon NULL
  4309.              * directory locks.
  4310.              */
  4311.  
  4312.         if(DevProc = GetDeviceProc(TheAssignment,DevProc))
  4313.         {
  4314.                 /* Set the default filesystem task. */
  4315.  
  4316.             SetFileSysTask(DevProc -> dvp_Port);
  4317.  
  4318.                 /* Is the lock on the list? */
  4319.  
  4320.             if(SameLock(DevProc -> dvp_Lock,TheLock) == LOCK_SAME)
  4321.                 Result = TRUE;
  4322.         }
  4323.         else
  4324.             break;
  4325.     }
  4326.     while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN) && !Result);
  4327.  
  4328.         /* Reset the default filesystem task. */
  4329.  
  4330.     SetFileSysTask(FileSysTask);
  4331.  
  4332.         /* Free device process data. */
  4333.  
  4334.     if(DevProc)
  4335.         FreeDeviceProc(DevProc);
  4336.  
  4337.     return(Result);
  4338. }
  4339.  
  4340.     /* DeleteBitMap(struct BitMap *BitMap):
  4341.      *
  4342.      *    Delete a bitmap created by CreateBitMap().
  4343.      */
  4344.  
  4345. VOID __regargs
  4346. DeleteBitMap(struct BitMap *BitMap)
  4347. {
  4348.     WaitBlit();
  4349.  
  4350.     if(Kick30)
  4351.         FreeBitMap(BitMap);
  4352.     else
  4353.     {
  4354.         LONG i;
  4355.  
  4356.         for(i = 0 ; i < BitMap -> Depth ; i++)
  4357.         {
  4358.             if(BitMap -> Planes[i])
  4359.                 FreeVec(BitMap -> Planes[i]);
  4360.         }
  4361.  
  4362.         FreeVecPooled(BitMap);
  4363.     }
  4364. }
  4365.  
  4366.     /* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
  4367.      *
  4368.      *    Create a new bitmap with given properties.
  4369.      */
  4370.  
  4371. struct BitMap * __regargs
  4372. CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
  4373. {
  4374.     if(Kick30)
  4375.         return(AllocBitMap(Width,Height,Depth,Flags,Friend));
  4376.     else
  4377.     {
  4378.         struct BitMap    *BitMap;
  4379.         LONG         Plus;
  4380.  
  4381.         if(Depth > 8)
  4382.             Plus = (Depth - 8) * sizeof(PLANEPTR);
  4383.         else
  4384.             Plus = 0;
  4385.  
  4386.         if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap) + Plus,MEMF_CLEAR))
  4387.         {
  4388.             LONG i,PageSize;
  4389.  
  4390.             InitBitMap(BitMap,Depth,Width,Height);
  4391.  
  4392.             PageSize = BitMap -> BytesPerRow * BitMap -> Rows;
  4393.  
  4394.             for(i = 0 ; i < BitMap -> Depth ; i++)
  4395.             {
  4396.                 if(!(BitMap -> Planes[i] = (PLANEPTR)AllocVec(PageSize,MEMF_CHIP)))
  4397.                 {
  4398.                     LONG j;
  4399.  
  4400.                     for(j = 0 ; j < i ; j++)
  4401.                         FreeVec(BitMap -> Planes[j]);
  4402.  
  4403.                     FreeVecPooled(BitMap);
  4404.  
  4405.                     return(NULL);
  4406.                 }
  4407.             }
  4408.  
  4409.             if(Flags & BMF_CLEAR)
  4410.                 BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
  4411.         }
  4412.  
  4413.         return(BitMap);
  4414.     }
  4415. }
  4416.  
  4417.     /* LaunchCommand(STRPTR Command):
  4418.      *
  4419.      *    Launch a command, try to figure out if it's an ARexx
  4420.      *    command, a plain batch file or a program and act
  4421.      *    accordingly.
  4422.      */
  4423.  
  4424. LONG __regargs
  4425. LaunchCommand(STRPTR Command)
  4426. {
  4427.     UBYTE    LocalBuffer[MAX_FILENAME_LENGTH];
  4428.     BPTR    Stream,
  4429.         OutputStream;
  4430.     APTR    OldConsoleTask    = ThisProcess -> pr_ConsoleTask;
  4431.     BOOL    IsScript    = FALSE,
  4432.         IsRexx        = FALSE;
  4433.     LONG    Result;
  4434.     BPTR    CommandFile;
  4435.     UBYTE    NameBuffer[MAX_FILENAME_LENGTH];
  4436.     BPTR    FileLock;
  4437.     STRPTR    OtherName;
  4438.     WORD    i;
  4439.  
  4440.         /* Chop off the arguments. */
  4441.  
  4442.     memcpy(NameBuffer,Command,MAX_FILENAME_LENGTH - 1);
  4443.  
  4444.     NameBuffer[MAX_FILENAME_LENGTH - 1] = 0;
  4445.  
  4446.     for(i = 0 ; i < MAX_FILENAME_LENGTH ; i++)
  4447.     {
  4448.         if(NameBuffer[i] == ' ')
  4449.         {
  4450.             NameBuffer[i] = 0;
  4451.             break;
  4452.         }
  4453.     }
  4454.  
  4455.         /* Now do something useful. Check if the command
  4456.          * could be an ARexx script.
  4457.          */
  4458.  
  4459.     if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
  4460.     {
  4461.         LONG Len;
  4462.  
  4463.             /* 256 bytes may be not be enough, but then
  4464.              * we're only guessing.
  4465.              */
  4466.  
  4467.         if((Len = Read(CommandFile,LocalBuffer,MAX_FILENAME_LENGTH)) > 0)
  4468.         {
  4469.             register UBYTE    c;
  4470.             LONG        i;
  4471.  
  4472.             for(i = 0 ; i < Len - 1 ; i++)
  4473.             {
  4474.                 c = LocalBuffer[i];
  4475.  
  4476.                     /* Stop on invalid characters. */
  4477.  
  4478.                 if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
  4479.                     break;
  4480.                 else
  4481.                 {
  4482.                         /* Looks like the typical
  4483.                          * introductory comment line.
  4484.                          */
  4485.  
  4486.                     if(c == '/' && LocalBuffer[i + 1] == '*')
  4487.                     {
  4488.                         IsRexx = TRUE;
  4489.                         break;
  4490.                     }
  4491.                 }
  4492.             }
  4493.         }
  4494.  
  4495.         Close(CommandFile);
  4496.     }
  4497.  
  4498.         /* Ok, second check. Does it have the script bit set? */
  4499.  
  4500.     if(FileLock = Lock(NameBuffer,ACCESS_READ))
  4501.     {
  4502.         struct FileInfoBlock __aligned FileInfo;
  4503.  
  4504.         if(Examine(FileLock,&FileInfo))
  4505.         {
  4506.             if(FileInfo . fib_Protection & FIBF_SCRIPT)
  4507.                 IsScript = TRUE;
  4508.         }
  4509.  
  4510.         UnLock(FileLock);
  4511.     }
  4512.  
  4513.         /* If it's an ARexx command, launch it. */
  4514.  
  4515.     if(IsRexx)
  4516.     {
  4517.         SendARexxCommand(Command,TRUE);
  4518.  
  4519.         return(0);
  4520.     }
  4521.  
  4522.         /* If it's a script command, prepend the "Execute "
  4523.          * command. It's not perfect but it should work.
  4524.          */
  4525.  
  4526.     if(IsScript)
  4527.     {
  4528.         if(OtherName = AllocVecPooled(strlen("Execute ") + strlen(Command) + 1,MEMF_ANY))
  4529.         {
  4530.             strcpy(OtherName,"Execute ");
  4531.             strcat(OtherName,Command);
  4532.  
  4533.             Command = OtherName;
  4534.         }
  4535.     }
  4536.     else
  4537.         OtherName = NULL;
  4538.  
  4539.     if(WindowName[0])
  4540.     {
  4541.         UBYTE LocalName[MAXPUBSCREENNAME + 1];
  4542.  
  4543.         if(Window)
  4544.         {
  4545.             if(!GetPubScreenName(Window -> WScreen,LocalName))
  4546.                 LocalName[0] = 0;
  4547.         }
  4548.  
  4549.         if(LocalName[0])
  4550.         {
  4551.             SPrintf(LocalBuffer,WindowName,LocalName);
  4552.  
  4553.             Stream = Open(LocalBuffer,MODE_NEWFILE);
  4554.         }
  4555.         else
  4556.             Stream = Open(WindowName,MODE_NEWFILE);
  4557.     }
  4558.     else
  4559.         Stream = NULL;
  4560.  
  4561.     if(GoodStream(Stream))
  4562.     {
  4563.         ThisProcess -> pr_ConsoleTask = ((struct FileHandle *)BADDR(Stream)) -> fh_Type;
  4564.  
  4565.         OutputStream = Open("*",MODE_NEWFILE);
  4566.     }
  4567.     else
  4568.         OutputStream = NULL;
  4569.  
  4570.     if(Stream && OutputStream)
  4571.     {
  4572.         Result = SystemTags(Command,
  4573.             SYS_Input,    Stream,
  4574.             SYS_Output,    OutputStream,
  4575.             SYS_UserShell,    TRUE,
  4576.         TAG_DONE);
  4577.     }
  4578.     else
  4579.     {
  4580.         Result = SystemTags(Command,
  4581.             SYS_UserShell,    TRUE,
  4582.         TAG_DONE);
  4583.     }
  4584.  
  4585.     if(OutputStream)
  4586.         Close(OutputStream);
  4587.  
  4588.     if(Stream)
  4589.         Close(Stream);
  4590.  
  4591.     ThisProcess -> pr_ConsoleTask = OldConsoleTask;
  4592.  
  4593.     if(OtherName)
  4594.         FreeVecPooled(OtherName);
  4595.  
  4596.     return(Result);
  4597. }
  4598.